c++ STL에서 가장 많이 쓰이는 컨테이너 중 하나인 std::vector의 복사는 효율적일까?
다음 코드를 실행시킨다 했을때
using namespace std;
class A
{
public:
A() { cout << "A 생성\n"; }
A(const A& other) { cout << "A 복사생성\n"; }
};
int main(void)
{
vector<A> temp1 = vector<A>(10);
vector<A> temp2 = temp1;
}
temp2에 temp1을 복사 할 경우 그림과 같이 요소의 개수 N(위 예제에서는 5)번 만큼의 복사생성자가 호출된다.
즉, vector의 복사생성자는 N개의 요소들을 각각 순차적으로 복사하는, O(N)의 시간복잡도를 갖게 된다.
궁금한 점은 vector는 연속된 메모리인데 비효율적으로 왜 모든 요소들을 각각 복사하는걸까? 연속된 메모리 구간을 통채로 복사해서(이를테면, memcpy와 같은) 복사하는게 아니라 각각 복사하는 것일까?
이유는 vector에 들어가는 데이터타입은 단순 데이터타입이 아니기 때문이다.
예를들면 float, int같이 기본 자료형이면 memcpy를 사용하는게 효율적일 수 있지만, shared_ptr<T>과 같이 생성자를 따로 정의하여 가지고 있는 경우, 해당 자료형의 생성자를 반드시 호출해주어야 한다. 만약 shared_ptr과 같이 특수한 동작을 하는 자료형의 경우, 그냥 메모리만 복사하게 되면 문제가 발생할 수 있기 때문이다!
shared_ptr<T>만 생각해 보더라도 당장 복사 생성자가 호출되지 않으면 참조 카운트가 증가하지 않게 되어 예상치 못한 작동을 일으킬 수 있다. vector와 같이 범용적으로 사용하도록 설계되어 있는 클래스 같은 경우는 효율성보다는 일관성을 중요시해야 하기 때문이다.
효율적인게 항상 옳지는 않다는 교훈을 얻게 되었다..
'C++' 카테고리의 다른 글
Class, Struct, Union 메모리 구조 (1) | 2024.07.08 |
---|---|
MySQL/MariaDB C/C++ 연동 (0) | 2024.04.25 |
함수 호출 규약(function call convention) : _cdecl, _stdcall, _fastcall (1) | 2024.01.27 |