
간단한 문제지만, string에선 substr로 빠르게 해결되는 문제지만 vector는 잘 모르겠어서 gemini에 물어봤다.
C++ 벡터 슬라이싱
벡터의 특정 부분을 복사해 새로운 벡터를 만들고 싶을 때, 두 개의 이터레이터를 사용하는 **범위 생성자(range constructor)**를 사용합니다.
- begin(): 벡터의 시작 위치를 가리키는 이터레이터입니다.
- end(): 벡터의 끝 바로 다음 위치를 가리키는 이터레이터입니다.
코드 예시
#include <iostream>
#include <vector>
int main() {
std::vector<int> original = {0, 10, 20, 30, 40, 50};
// 인덱스 2부터 4까지 슬라이싱 (20, 30, 40)
// original.begin() + 2: 시작 위치
// original.begin() + 5: 끝 위치 (포함하지 않음)
std::vector<int> sliced(original.begin() + 2, original.begin() + 5);
// 슬라이싱 결과 출력
for (int num : sliced) {
std::cout << num << " "; // 20 30 40
}
std::cout << std::endl;
return 0;
}
C++ 문자열 슬라이싱
말씀하신 대로, std::string은 substr 멤버 함수를 사용해 매우 직관적으로 슬라이싱할 수 있습니다.
- substr(시작 인덱스, 길이)
코드 예시
#include <iostream>
#include <string>
int main() {
std::string original = "hello world";
// 인덱스 6부터 5글자 슬라이싱 ("world")
std::string sliced = original.substr(6, 5);
std::cout << sliced << std::endl; // world
return 0;
}
요약
| 자료형 | 슬라이싱 방법 | 설명 |
| std::vector | vector(시작_이터레이터, 끝_이터레이터) | 범위 생성자를 이용한 복사 |
| std::string | substr(시작_인덱스, 길이) | 내장 멤버 함수 사용 |
그러고 vector의 생성 방식 중 이런 방식이 있는지 몰랐어서 정리했다.
### vector 생성 방법 2가지
- 채우기 생성자 (Fill Constructor)
- 형태: vector<int> my_vector(개수, 초기화할_값);
- 설명: 지정한 개수만큼의 공간을 만들고 모든 요소를 동일한 초기화할_값으로 채워서 벡터를 생성합니다.
- 범위 생성자 (Range Constructor)
- 형태: vector<int> my_vector(시작_이터레이터, 끝_이터레이터);
- 설명: 다른 컨테이너(예: 다른 벡터나 배열)의 시작 위치부터 끝 위치 바로 앞까지의 모든 요소를 복사해서 새로운 벡터를 만듭니다.
그러나 answer = (num_list.begin(), num_list.begin() + b + 1); 처럼 따로 하나씩 만드니까 오류가 발생했다.
answer.assign(num_list.begin(), num_list.begin() + b + 1); 이런식으로 assign으로 재할당해줘야 했다.
그런 이유는 타입 불일치이기 때문.
### 왜 일반 대입(=)은 안 될까?
컴퓨터(컴파일러)는 타입을 매우 엄격하게 구분합니다. vector<int> 타입의 변수에는 vector<int> 타입의 값만 대입할 수 있습니다.
- vector<int>: '정수를 담는 상자' 자체입니다.
- vector<int>::iterator: 상자 안의 **'특정 물건을 가리키는 포인터 또는 책갈피'**입니다.
answer = (num_list.begin(), num_list.end()); 와 같은 코드는 **'상자'**에 **'책갈피'**를 넣으려는 시도와 같습니다. 둘은 완전히 다른 종류이기 때문에 C++ 컴파일러가 "타입이 맞지 않아서 대입할 수 없습니다."라는 오류를 발생시킵니다.
vector<int> answer;
vector<int> original = {1, 2, 3, 4};
// 아래 코드는 컴파일 에러 발생!
// error: cannot convert ‘std::vector<int>::iterator’ to ‘std::vector<int>’
answer = original.begin();
### 올바른 방법 2가지
그래서 C++는 이터레이터 범위를 다루는 두 가지 방법을 명확하게 구분해서 제공합니다.
- 생성자 (선언과 동시에 초기화)
- vector<int> answer(original.begin(), original.end());
- answer라는 벡터가 태어날 때부터 original의 특정 범위를 복사해서 태어나도록 하는 것입니다.
- assign 메소드 (이미 있는 벡터의 내용 교체)
- answer.assign(original.begin(), original.end());
- 이미 존재하는 answer 벡터의 기존 내용을 싹 지우고, 지정된 범위의 새로운 내용으로 갈아끼우는 것입니다.
결론적으로, 이터레이터를 사용하는 것은 생성할 때와 그 이후 모두 가능하지만, 그 이후에는 반드시 assign이라는 전용 메소드를 사용해야 합니다.
'개발 공부 > 코딩 공부' 카테고리의 다른 글
| C++ 람다식 (0) | 2025.09.16 |
|---|---|
| C++ 입출력 (0) | 2025.09.15 |
| c++ <limits>, const &auto (0) | 2025.09.03 |
| 복사와 함수 인자 전달 , 그리고 메모리 (0) | 2025.09.03 |
| 간단한 수학 공식들 (1) | 2025.09.01 |