안녕하세요, 여러분! 오늘은 C++ STL의 꽃이라고 할 수 있는 vector
에 대해 함께 알아보는 시간을 가져보려고 해요. 마치 만능 주머니처럼 자유자재로 요소를 추가하고 삭제할 수 있는 vector
는 정말 매력적이지 않나요? 프로그래밍을 하다 보면 데이터를 효율적으로 관리해야 할 때가 정말 많은데, 이럴 때 vector
만큼 든든한 친구도 없답니다. 요소 추가
, 삭제
, 접근
등 vector
의 다양한 사용법을 제대로 익히면 코딩 실력이 쑥쑥 향상될 거예요. 자, 그럼 지금부터 벡터 생성 및 초기화
부터 요소 접근
까지 차근차근 살펴보도록 할까요? 함께 즐겁게 vector
의 세계로 빠져들어 봐요!
C++ STL의 vector
는 동적 배열처럼 작동하는 컨테이너예요. 크기가 자동으로 조정되니 얼마나 편한지 몰라요! 자, 그럼 이 마법 상자를 어떻게 만드는지, 또 어떤 마법의 주문을 걸 수 있는지 하나씩 알아볼까요?
먼저, vector
를 사용하려면 <vector>
헤더 파일을 포함해야 해요. 잊지 마세요!
#include <vector>
자, 이제 vector
를 만들어 볼게요. vector
는 다양한 자료형을 저장할 수 있어요. 정수, 실수, 문자열, 심지어 사용자 정의 클래스까지도 가능해요! vector
를 생성하는 방법은 여러 가지가 있어요. 가장 기본적인 방법은 다음과 같아요.
std::vector<int> vec; // int형 벡터 생성, 요소 없음
이렇게 하면 비어있는 int
형 벡터 vec
가 생성돼요. 초기값을 넣어서 생성하고 싶다면 어떻게 해야 할까요? 여러 가지 방법이 있지만, 몇 가지 예시를 보여드릴게요.
std::vector<int> vec1 = {1, 2, 3, 4, 5}; // 초기값을 직접 넣어 생성!
std::vector<double> vec2(3, 3.14); // 크기가 3이고 모든 요소가 3.14인 double형 벡터 생성!
std::vector<std::string> vec3(5, "hello"); // 크기가 5이고 모든 요소가 "hello"인 string형 벡터 생성!
std::vector<int> vec4(vec1); // vec1을 복사해서 vec4 생성!
std::vector<int> vec5(vec1.begin(), vec1.begin() + 3); // vec1의 처음 세 요소를 복사해서 vec5 생성!
각각의 방법을 좀 더 자세히 살펴볼까요? 첫 번째 방법은 초기값 리스트를 사용해서 벡터를 생성하는 방법이에요. {}
괄호 안에 초기값들을 넣어주면 돼요. 간단하죠? 두 번째 방법은 벡터의 크기와 초기값을 지정해서 생성하는 방법이에요. vec2
처럼 크기가 3이고 모든 요소가 3.14인 double
형 벡터를 만들 수 있어요. 세 번째 방법도 비슷해요. 크기와 초기값을 지정해서 문자열 벡터를 만들 수 있답니다. 네 번째 방법은 다른 벡터를 복사해서 새로운 벡터를 생성하는 방법이에요. vec1
의 모든 요소가 vec4
에 복사돼요. 마지막 방법은 iterator를 사용해서 벡터의 일부분을 복사하는 방법이에요. vec1
의 처음 세 요소만 vec5
에 복사되는 거죠!
vector
의 크기를 변경하고 싶으면 어떻게 해야 할까요? resize()
함수를 사용하면 돼요!
std::vector<int> vec = {1, 2, 3};
vec.resize(5); // 크기를 5로 변경! 부족한 부분은 0으로 채워져요!
std::cout << vec.size(); // 출력: 5
vec
의 크기가 5로 변경되었고, 부족한 두 자리는 0으로 채워졌어요. 만약 특정 값으로 채우고 싶다면 두 번째 인자로 값을 넣어주면 돼요.
vec.resize(8, 99); // 크기를 8로 변경하고, 99로 채워요!
이제 vec
의 크기는 8이고, 새로 추가된 다섯 자리는 99로 채워져요! vector
는 크기가 동적으로 변경되기 때문에 메모리 관리 측면에서도 효율적이에요. 필요한 만큼만 메모리를 사용하니까요! vector
는 C++에서 가장 많이 사용되는 컨테이너 중 하나예요. 다양한 기능을 제공하고 사용하기도 편리하기 때문이죠!
자, 이제 벡터에 요소를 추가하는 다양한 방법을 알아볼까요? 마치 레고 블록을 쌓듯이, 원하는 요소들을 차곡차곡 넣어 벡터를 풍성하게 만들 수 있답니다! C++ STL의 vector
는 동적 배열로, 크기가 자동으로 조정되기 때문에 요소 추가가 매우 편리해요. 마법 같죠? ^^
가장 기본적인 방법은 push_back()
함수를 사용하는 거예요. 이 함수는 벡터의 맨 뒤에 새로운 요소를 추가한답니다. 예를 들어, 숫자 1부터 5까지를 벡터에 추가하고 싶다면 다음과 같이 작성할 수 있어요. 참 쉽죠?!
#include <iostream>
#include <vector>
int main() {
std::vector<int> myVector;
myVector.push_back(1);
myVector.push_back(2);
myVector.push_back(3);
myVector.push_back(4);
myVector.push_back(5);
return 0;
}
push_back()
은 벡터의 크기를 자동으로 늘려주기 때문에, 용량 걱정 없이 요소를 추가할 수 있다는 장점이 있어요! 벡터의 크기를 미리 알고 있다면 reserve()
함수를 사용하여 메모리 할당 횟수를 줄이고 성능을 향상시킬 수도 있답니다. reserve()
는 벡터의 용량을 예약하는 함수인데, 예를 들어 처음부터 100개의 요소를 추가할 예정이라면 myVector.reserve(100);
과 같이 사용할 수 있어요. 이렇게 하면 메모리 재할당 횟수가 줄어들어 효율적이겠죠?
push_back()
외에도 insert()
함수를 사용하면 벡터의 특정 위치에 요소를 삽입할 수 있어요. insert()
함수는 iterator를 사용하는데, iterator는 벡터의 특정 요소를 가리키는 포인터와 같은 역할을 해요. 예를 들어, 벡터의 두 번째 위치에 숫자 10을 삽입하고 싶다면 다음과 같이 작성할 수 있답니다.
#include <iostream>
#include <vector>
int main() {
std::vector<int> myVector;
myVector.push_back(1);
myVector.push_back(2);
// 벡터의 begin() + 1 위치, 즉 두 번째 위치에 10을 삽입합니다.
myVector.insert(myVector.begin() + 1, 10);
return 0;
}
myVector.begin()
은 벡터의 첫 번째 요소를 가리키는 iterator를 반환하고, 여기에 1을 더하면 두 번째 요소를 가리키게 되는 거예요. insert()
함수는 지정된 위치에 새로운 요소를 삽입하고, 기존 요소들은 뒤로 한 칸씩 이동한답니다. 마치 손님이 꽉 찬 버스에 새로운 승객이 타면 자리를 만들어주는 것과 같은 원리예요! insert()
함수를 사용할 때 주의할 점은, 삽입 위치가 벡터의 크기를 넘어가면 안 된다는 거예요. 만약 범위를 벗어난 위치에 삽입하려고 하면 프로그램이 오류를 발생시킬 수 있으니 조심해야 해요!
또한, insert()
함수를 사용하여 여러 개의 요소를 한 번에 추가할 수도 있어요. 예를 들어, 벡터의 세 번째 위치에 숫자 20부터 24까지 5개의 요소를 추가하고 싶다면 다음과 같이 작성할 수 있답니다.
#include <iostream>
#include <vector>
#include <numeric>
int main() {
std::vector<int> myVector = {1, 2, 3};
// 20부터 24까지의 숫자를 생성하여 tempVector에 저장합니다.
std::vector<int> tempVector(5);
std::iota(tempVector.begin(), tempVector.end(), 20);
// myVector의 세 번째 위치(begin() + 2)에 tempVector의 모든 요소를 삽입합니다.
myVector.insert(myVector.begin() + 2, tempVector.begin(), tempVector.end());
return 0;
}
insert()
함수의 세 번째와 네 번째 인자로 삽입할 요소의 시작과 끝 iterator를 지정해주면 된답니다. insert()
함수를 사용할 때는 iterator의 개념을 잘 이해하는 것이 중요해요! iterator는 벡터의 요소를 가리키는 포인터와 같은 역할을 하기 때문에, iterator를 잘못 사용하면 예상치 못한 결과가 발생할 수 있으니 주의해야 한답니다!
emplace_back()
함수는 C++11에서 추가된 기능인데, push_back()
과 비슷하지만 더 효율적인 방법으로 요소를 추가할 수 있어요. push_back()
은 먼저 요소를 생성한 다음 벡터에 복사하지만, emplace_back()
은 벡터 내부에서 직접 요소를 생성하기 때문에 복사 과정이 생략되어 성능이 향상될 수 있답니다. 특히 복잡한 객체를 추가할 때 emplace_back()
을 사용하면 성능 차이가 더욱 커질 수 있어요. emplace_back()
은 객체를 생성하는 데 필요한 인자들을 직접 전달받아 벡터 내부에서 객체를 생성한답니다. 신기하죠?
이처럼 C++ STL의 vector
는 다양한 방법으로 요소를 추가할 수 있도록 지원하고 있어요. 각 함수의 특징과 사용법을 잘 이해하고 상황에 맞는 함수를 사용하면 더욱 효율적이고 안전하게 벡터를 사용할 수 있답니다! 다음에는 벡터에서 요소를 삭제하는 방법에 대해 알아볼게요! 기대해 주세요~?
자, 이제 벡터에서 원소를 삭제하는 방법에 대해 알아볼까요? 생각보다 다양한 방법이 있고, 각각의 특징이 있으니 잘 따라와 주세요! 벡터의 크기가 동적으로 변한다는 점, 잊지 않으셨죠? 삭제 작업 후에는 벡터의 크기가 줄어들고, 메모리 관리도 자동으로 이루어진답니다!
C++ STL의 <vector>
는 요소 삭제를 위해 pop_back()
, erase()
, clear()
등 다양한 멤버 함수를 제공해요. 각 함수의 시간 복잡도와 사용법을 제대로 이해하는 것이 성능 최적화의 핵심이라고 할 수 있죠! 벡터에서 요소를 삭제할 때, 잘못된 방법을 사용하면 프로그램이 예상치 못한 동작을 하거나 심지어 크래시가 발생할 수도 있어요. 그러니 각 함수의 특징을 제대로 파악하고 상황에 맞는 함수를 사용하는 것이 정말 중요해요!
pop_back()
벡터의 맨 마지막 요소를 삭제하는 가장 간단한 방법이에요. 시간 복잡도는 상수 시간, 즉 O(1)이라서 매우 빠르죠. 벡터가 비어있는 상태에서 pop_back()
을 호출하면 정의되지 않은 동작이 발생할 수 있으니, 사용 전에 empty()
로 벡터가 비어있는지 확인하는 습관을 들이는 게 좋겠죠? 예를 들어, 1000개의 요소가 있는 벡터에서 마지막 요소를 삭제하는 데에는 1ms도 걸리지 않을 거예요. 하지만, 맨 마지막 요소가 아닌 다른 요소를 삭제하려면 erase()
를 사용해야 한다는 점! 꼭 기억해 두세요!
#include <iostream>
#include <vector>
int main() {
std::vector<int> myVector = {1, 2, 3, 4, 5};
myVector.pop_back(); // 5가 삭제됩니다!
// 이제 myVector는 {1, 2, 3, 4}가 됩니다.
return 0;
}
erase()
특정 위치 또는 범위의 요소를 삭제할 때 사용하는 함수입니다. pop_back()
보다 훨씬 유연하지만, 시간 복잡도는 삭제되는 요소의 개수와 위치에 따라 선형 시간, 즉 O(n)까지 증가할 수 있어요. (n은 벡터의 크기) 특히 벡터의 앞부분에서 요소를 삭제하면, 뒤에 있는 모든 요소들이 한 칸씩 앞으로 이동해야 하기 때문에 시간이 오래 걸릴 수 있다는 점, 주의해야 해요!
이터레이터를 사용하여 특정 위치의 요소를 삭제할 수 있어요.
#include <iostream>
#include <vector>
int main() {
std::vector<int> myVector = {1, 2, 3, 4, 5};
myVector.erase(myVector.begin() + 2); // 인덱스 2의 요소 (3) 삭제
// 이제 myVector는 {1, 2, 4, 5}가 됩니다.
return 0;
}
시작과 끝 이터레이터를 지정하여 특정 범위의 요소를 한 번에 삭제할 수도 있어요. 범위는 시작 이터레이터부터 끝 이터레이터 바로 전까지라는 점, 잊지 마세요!
#include <iostream>
#include <vector>
int main() {
std::vector<int> myVector = {1, 2, 3, 4, 5};
myVector.erase(myVector.begin() + 1, myVector.begin() + 4); // 인덱스 1부터 3까지 (2, 3, 4) 삭제
// myVector는 {1, 5}가 됩니다.
return 0;
}
clear()
벡터의 모든 요소를 삭제하고 벡터를 비웁니다. 시간 복잡도는 벡터의 크기에 비례하는 선형 시간, O(n)입니다. clear()
를 사용하면 벡터의 크기가 0이 되지만, 할당된 메모리는 그대로 유지된다는 점! (용량은 변하지 않아요) 메모리까지 완전히 해제하려면 clear()
후에 shrink_to_fit()
을 호출하거나, swap trick (std::vector<T>().swap(myVector)
)을 사용하는 것이 좋습니다.
#include <iostream>
#include <vector>
int main() {
std::vector<int> myVector = {1, 2, 3, 4, 5};
myVector.clear(); // 모든 요소 삭제!
// myVector는 이제 비어있습니다.
return 0;
}
자, 이제 벡터에서 요소를 삭제하는 다양한 방법들을 알아보았어요! 각 함수의 시간 복잡도와 특징을 잘 이해하고 상황에 맞게 사용하면, 효율적이고 안전하게 벡터를 관리할 수 있을 거예요. 다음에는 벡터 요소에 접근하는 방법에 대해 알아보도록 할게요! 기대해 주세요!
자, 이제 벡터에 원하는 데이터들을 예쁘게 담았으니 이 데이터들을 어떻게 꺼내 쓸 수 있는지 알아볼 차례예요! 마치 보물상자에서 원하는 보물을 꺼내듯이 말이죠! C++ STL 벡터는 다양한 방법으로 요소에 접근할 수 있도록 여러 가지 기능들을 제공한답니다. 각각의 방법들을 하나씩 살펴보면서 여러분의 코딩 실력을 한 단계 업그레이드해 보아요~!
가장 기본적이고, 직관적인 방법은 []
연산자, 즉 대괄호 연산자를 사용하는 거예요. 마치 배열처럼 말이죠! 예를 들어 vector<int> myVector = {10, 20, 30, 40, 50};
이렇게 벡터를 선언하고, 세 번째 요소(30)에 접근하고 싶다면 myVector[2]
라고 하면 된답니다. 인덱스는 0부터 시작한다는 점, 잊지 마세요?! 만약 myVector[5]
처럼 존재하지 않는 인덱스에 접근하려고 하면 어떻게 될까요? 프로그램이 크래시 날 수도 있어요! (런타임 에러!) 이런 상황을 방지하려면 at()
메서드를 사용하는 것이 훨씬 안전해요.
at()
메서드는 []
연산자와 기능은 비슷하지만, 범위를 벗어난 인덱스에 접근하면 std::out_of_range
예외를 던져준답니다. 훨씬 안전하죠? 예외 처리를 통해 프로그램의 안정성을 높일 수 있다는 장점이 있어요! 예를 들어 myVector.at(2)
는 세 번째 요소(30)를 안전하게 반환해주지만, myVector.at(10)
과 같이 범위를 벗어난 인덱스를 사용하면 예외가 발생하고, 이를 try-catch
문으로 잡아서 적절히 처리할 수 있답니다. 프로그램이 갑자기 죽는 것보다는 훨씬 낫겠죠?
벡터의 첫 번째 요소와 마지막 요소에 접근하는 특별한 방법도 있어요. front()
메서드는 벡터의 첫 번째 요소에 대한 참조를 반환하고, back()
메서드는 벡터의 마지막 요소에 대한 참조를 반환해요. myVector.front()
는 10을, myVector.back()
은 50을 반환하겠죠? 이 메서드들을 사용하면 벡터의 시작과 끝 요소에 쉽고 빠르게 접근할 수 있어요. 특히 큐나 스택처럼 자료구조를 구현할 때 아주 유용하게 사용할 수 있답니다!
자, 이제 벡터의 요소들을 하나씩 순차적으로 접근하는 방법을 알아볼까요? 반복문을 사용하는 것이 일반적이지만, C++에서는 더욱 효율적이고 세련된 방법을 제공해요. 바로 iterator(반복자)를 사용하는 것이죠! 마치 벡터를 가리키는 포인터처럼 생각하면 돼요. begin()
메서드는 벡터의 첫 번째 요소를 가리키는 iterator를 반환하고, end()
메서드는 벡터의 마지막 요소 다음을 가리키는 iterator를 반환해요. end()
가 마지막 요소를 가리키는 게 아니라, 마지막 요소 다음을 가리킨다는 점! 꼭 기억하세요!
#include <iostream>
#include <vector>
int main() {
std::vector<int> myVector = {10, 20, 30, 40, 50};
for (std::vector<int>::iterator it = myVector.begin(); it != myVector.end(); ++it) {
std::cout << *it << " "; // iterator가 가리키는 값에 접근하려면 * 연산자를 사용해야 해요!
}
std::cout << std::endl;
// C++11 이후부터는 range-based for loop를 사용하여 더 간결하게 표현할 수 있어요!
for (int value : myVector) {
std::cout << value << " ";
}
std::cout << std::endl;
return 0;
}
위 코드처럼 iterator를 사용하면 벡터의 모든 요소를 순차적으로 접근할 수 있답니다. C++11 이후부터는 range-based for loop를 사용하여 더 간결하게 표현할 수도 있어요! 훨씬 깔끔하죠? 코드가 짧아지면 오류 발생 가능성도 줄어들고, 가독성도 좋아진답니다.
rbegin()
과 rend()
메서드는 역방향 iterator를 반환해요. rbegin()
은 벡터의 마지막 요소를 가리키고, rend()
는 벡터의 첫 번째 요소 앞을 가리킨답니다. 이 메서드들을 사용하면 벡터의 요소들을 역순으로 접근할 수 있어요. 가끔씩 필요한 기능이니 알아두면 좋겠죠?
벡터 요소에 접근하는 방법, 이제 완벽하게 이해하셨나요? 다양한 방법들을 적재적소에 활용하여 여러분의 C++ 코딩 실력을 한층 더 업그레이드해보세요!
자, 이렇게 C++ STL vector에 대해 알아봤어요! 생성부터 초기화, 요소 추가, 삭제, 그리고 접근까지, 어떤가요? 이제 좀 친숙해진 느낌이 드나요? 처음엔 조금 낯설 수 있지만, 몇 번 연습하다 보면 금방 손에 익을 거예요. 벡터는 정말 강력하고 유용한 도구니까요. 마치 요술 상자처럼 다양하게 활용할 수 있답니다! 앞으로 C++ 프로그래밍하면서 벡터와 더욱 친해져 보세요. 분명 코딩하는 재미가 더 쏠쏠해질 거예요. 이 글이 여러분의 C++ 여정에 조금이나마 도움이 되었으면 좋겠네요. 다음에 또 만나요!
안녕하세요! 리눅스, 처음엔 낯설고 어렵게 느껴지셨죠? 저도 그랬어요. 마치 미지의 세계에 발을 들여놓은 기분이랄까요? 하지만…
안녕하세요! 오늘은 리눅스의 세계로 함께 여행을 떠나볼까 해요. 수많은 리눅스 배포판 중에서도 가장 인기 있는…
This website uses cookies.