2012-07-20 3 views
17

가정하자 나는 다음과 같은 코드를 가지고 :이동 ::와 push_back

#include <vector> 
struct A { 
    int a; 
    int x; 
}; 
int main() { 
    using namespace std; 
    A a1; 
    A a2; 
    vector<A> va; 
    va.push_back(a1); 
    va.push_back(move(a2)); 
} 

나는 표준 : : 벡터의 요소가 표준 : 목록과는 달리, 연속 저장되어 있음을 알고 있습니다. 위의 코드에서 a2은 이동되었지만 vaa2의 복사가 실제로 있습니까? va.push_back(a2);과 의 차이점은 무엇입니까? 당신이 va.push_back(move(a2)) 버전 vector<T>::push_back(T&&)가 호출 될 사용할 때 va.push_back(a2) 버전 vector<T>::push_back(const T&)를 사용

+2

'std :: move'a2는 평면 유형 (즉, 외부 데이터 없음)이기 때문에 그대로 복사합니다. – Xeo

+0

@cdhowie 감사합니다. 수정 됨. – ggg

+0

의미 이동에 대한 소개는 [다른 사람이 나에게 의미 이동을 설명 할 수 있습니까?] (http://stackoverflow.com/questions/3106110/)를 참조하십시오. – fredoverflow

답변

26

귀하의 경우에는 컴파일러가 제공하는 복사 생성자를 사용하므로 실제적인 차이점은 없습니다. 움직일 수있는 객체를 사용할 때 눈에 띄는 성능 차이가 발생하고 복사에 많은 노력을 기울일 것입니다. 이 경우 push_back(x)을 사용하면 push_back(move(x))x의 내용을 "훔칠"수 있으며 x은 사용할 수없고 정의되지 않은 상태로 남게됩니다. push_back(move(x))push_back()에게이 개체의 복사본을 만듭니다.

목록 벡터 (std::vector<std::list<int> >)가 있고 100,000 개의 요소가 포함 된 목록을 푸시하려는 경우를 고려하십시오. move()이 없으면 전체 목록 구조와 모든 100,000 개의 요소가 복사됩니다. move()을 사용하면 일부 포인터와 기타 작은 비트의 데이터가 뒤죽박죽으로 전달됩니다. 이것은 훨씬 더 빠르며 전반적인 메모리 소비는 더 적게 필요합니다.

+1

왜? c-tor가 자동으로 생성됩니다. – ForEveR

+6

@ForEveR 이동할 수있는 A 구조체에 할당이 없기 때문에 자동으로 생성되는지 여부는 중요하지 않습니다. 당신은 단지 두 개의'int'를 가지고 있고, move 생성자는 복사 생성자가 할 일과 같은 일을 할 것입니다 : 소스 객체의 int에 저장된 값을 새로운 객체에 할당하십시오. 이 유형의 이동 시나리오에서는 최적화가 가능할만큼 최적화 된 상태이므로 최적화 할 가능성이 없습니다. – cdhowie

+0

@cdhowie 그래서 이동 중에 항상 무언가가 복사됩니까? – ggg

14

은 성능에 대 한 차이가없는

그러나 귀하의 경우,

15

때문에 ..., 호출됩니다 비노 동 클래스의 암시 적으로 정의 된 복사/이동 생성자 X는 기본 및 멤버의 멤버 별 복사/이동을 수행합니다.

단락 12.8 n3337 draft.

0

나는 다른 답변이 끝나지 않은 것을 메모하고 싶습니다. 이동 생성자가 이동 된 객체를 설정해야하기 때문에 ?.push_back(move(?))?.push_back(?)보다 느릴 수 있습니다 (실제로 복사 가능한 객체가있는 경우). 두 객체를 효과적으로 복사하는 중입니다.

+0

이동 생성자는 이동 된 객체에 아무 것도하지 않아도됩니다. null로 재설정해야하는 포인터를 이동하지 않으면 아무 것도 0으로 설정할 필요가 없습니다. (컴파일러 생성 move 생성자는 소스 객체를 블랭킷 0으로 만들지 않습니다.) – cdhowie