Quick Reference
가변 길이 값 묶음에는 vector, 가변 텍스트에는 string을 먼저 씁니다. 삽입 수를 짐작할 수 있으면 reserve로 필요한 용량을 미리 확보하되, 이는 원소를 만들지 않으며 용량을 넘기기 전까지만 재할당을 피합니다.
#include <iostream>
#include <string>
#include <vector>
int main() {
std::vector<int> values;
values.reserve(4);
values.push_back(1);
values.emplace_back(2);
std::string text{"Hello"};
text += ", World";
std::cout << values.at(1) << ", " << text.substr(0, 5) << '\n';
}문법
먼저 보는 기본형은 아래입니다.
vector생성과push_backreserve와size/capacitystring연결과 부분 문자열- 인덱스 접근과
at()
어떤 기본 컨테이너를 먼저 고르면 되나
| 상황 | 먼저 떠올릴 것 |
|---|---|
| 가변 길이 값 묶음 | std::vector |
| 가변 텍스트 | std::string |
| 삽입 수를 대략 안다 | reserve() |
| 경계 검사까지 필요 | at() |
| 객체를 바로 만들며 넣기 | emplace_back() |
std::vector<int> numbers{1, 2, 3};
numbers.push_back(4);
std::string name = "Ref";
name += "Dock";vector는 커지면서 재할당할 수 있다
vector는 내부적으로 연속 배열을 유지합니다. 용량이 부족하면 더 큰 저장소를 할당하고 원소를 이동하거나 복사합니다. 성장 비율은 구현이 정하며, push_back의 분할 상환 비용이 상수 시간이라는 점만 표준적으로 기대할 수 있습니다. 재할당이 일어나면 기존 원소를 가리키던 모든 반복자와 포인터가 무효화됩니다.
std::vector<int> v;
// 삽입 수를 알면 reserve — 확보한 capacity 안에서는 삽입 중 재할당 없음
v.reserve(1000);
for (int i = 0; i < 1000; ++i) v.push_back(i); // 재할당 0회
// 주의: reserve 후에도 size()는 0
std::cout << v.size(); // 0 (아직 비어 있음)
std::cout << v.capacity(); // 1000 (메모리만 확보)push_back은 이미 만든 객체를 벡터에 복사하거나 이동합니다. emplace_back은 인자를 받아 벡터 내부에서 직접 객체를 생성합니다. 다만 이미 객체가 있거나 인자 변환이 같은 경우에는 더 빠르다는 보장이 없으므로, 의미가 더 직접적인 쪽을 고릅니다.
std::vector<std::pair<int, std::string>> v;
v.push_back({1, "one"}); // pair 임시 생성 후 이동
v.emplace_back(1, "one"); // 벡터 안에서 pair 직접 생성 (효율적)
v.emplace_back(std::make_pair(1, "one")); // 이것도 가능하지만 중간 단계 있음// ❌ reserve만 해두고 원소가 생겼다고 착각
std::vector<int> values;
values.reserve(10);
// values[0] = 1;
// ✅ 원소를 실제로 만들려면 push_back / resize
values.push_back(1);
values.resize(10);많은 표준 라이브러리 구현은 짧은 문자열을 객체 안에 직접 저장하는 SSO(Small String Optimization)를 사용합니다. 다만 SSO의 존재와 임계 길이는 표준 보장이 아니므로, 특정 글자 수나 성능을 API 계약으로 가정하지 않습니다.
std::string s = "Hello, World!";
// 기본 조작
s.size(); // 13 (바이트 수)
s.empty(); // false
s += "!"; // 이어 붙이기
s.substr(0, 5); // "Hello"
s.find("World"); // 7 (없으면 string::npos)
s[0]; // 'H'
// 변환
int n = std::stoi("42"); // 문자열 → 정수
std::string str = std::to_string(42); // 정수 → 문자열선택 기준
- 원소 수를 모으는 기본 컨테이너:
vector - 가변 텍스트:
string - 삽입 전 크기를 대략 알면
reserve - 이미 만든 객체를 넣으면
push_back - 인자로 바로 만들면
emplace_back - 경계 검사까지 원하면
at()
주의할 점
vector에 원소를 추가하면 재할당이 일어날 수 있고 기존 반복자·포인터·참조가 무효화됩니다.
std::vector<int> v{1, 2, 3};
int* ptr = &v[0]; // v[0]의 주소
v.push_back(4); // 재할당 발생 가능
std::cout << *ptr; // ❌ ptr이 이미 해제된 메모리를 가리킬 수 있음
// ✅ 재할당 없도록 미리 reserve
v.reserve(10);
int* ptr2 = &v[0];
v.push_back(4); // capacity 안에서 — ptr2 여전히 유효// ❌ reserve는 메모리만 확보하고 원소를 만들지 않는다
std::vector<int> values;
values.reserve(10);
values[0] = 1; // 잘못된 접근
// ✅ 원소를 실제로 만들려면 push_back 또는 resize
values.push_back(1);참고 링크
2 sources