2013-11-27 2 views
2

편집 : 아래의 코드는 이동 의미를 사용하여 다시 쓰고 두 가지 접근 방식을 비교할 수 있도록 저속 (과도한 복사)을 원합니다.이동 의미가 좋은 방법에 대한 좋은 예

I이 클래스에 다음 코드 : 이제

std::list<boost::shared_ptr<I> > getX(){ 
    std::list<boost::shared_ptr<I> > a; 

    for(auto kv : b) { 
     if(something){ 
      a.push_back(kv.second); 
     } 
    } 

    return a; 
} 

double foo(){ 

    std::list<boost::shared_ptr<I> > a = getX(); 

내가 return a에 중단 점을 넣어 내가 만들어지고 목록의 사본의 일종합니다 (std::list 복사 생성자를 볼 것으로 예상되고 . 내가보고 기대했다 이루어지고

LEAF_ENTRY __security_check_cookie, _TEXT 

cmp rcx, __security_cookie  ; check cookie value in frame 
jne ReportFailure    ; if ne, cookie check failure 
rol rcx, 16      ; make sure high word is zero 
test cx, -1 
jne RestoreRcx 
db 0f3h       ; (encode REP for REP RET) 
ret        ; no overrun, use REP RET to avoid AMD 
           ; branch prediction flaw after Jcc 

나는 목록의 사본을 볼 수 없습니다 :. 다음 그러나, 대신 디버거가 침입 각 I 객체 복사 생성자는 amdsecgs.asm하기 복사 된 목록과 I 개체가 복사됩니다.

(내가 움직이는 의미를 사용하여 속도를 높이는 데 도움이되는 코드를 작성하려고하기 때문에이 질문을하는 이유가 여기에 있습니다.)

이 코드는 반환 값 최적화를 통해 최적화됩니까? 그렇다면 RVO가 적용되는 것을 막기 위해 코드를 고칠 수있는 방법이 있습니까?

+0

필자는 원래 목록이 스택 자동 개체이고 범위를 벗어나면 파괴되므로 목록을 복사하여 복사한다는 것을 이해합니다. 할당되면 다시 복사되지 않습니다. 왜냐하면 이동 의미론 때문에. 왜 이제 힙에 목록을 만들고 대신 스마트 포인터를 반환하고 있습니까? 그러면 모든 복사가 제거됩니다. – Julius

+0

@Julius 나는 이동 의미론의 장점을 (코드를 다시 작성하여) 보여주기 위해 사본을 만들고 싶습니다 .... – user997112

답변

0

하나의 옵션이 될 수 : RVO/NRVO을 중단하고 반환 된 목록을 복사하도록 컴파일러에 강제적으로

std::list<boost::shared_ptr<I> > getX(){ 
    using list = std::list<boost::shared_ptr<I> >; 
    list empty; 
    list a; 

    for(auto kv : b) { 
     if(something){ 
      a.push_back(kv.second); 
     } 
    } 

    return list(a.empty() ? empty : a); 
} 

.

0

이동 의미에 의해 제공되는 속도 향상을 보여 주기만하면 자동 스코핑 된 콜렉션을 범위 내에서 이동할 때와 같이 실제로 유용하게 컴파일러와 싸울 필요가없는 경우를 사용할 수 있습니다 그래서 같은 : 그래서 여기

typedef vector<float> Grades; 
unordered_map<int, string> idsToNames; 
unordered_map<int, Grades> idsToGrades; 
//ids and names being used seperatly 
... 
//it would now be more useful to merge them 
struct StudentInfo { 
    string mName; Grades mGrades; 
    StudentInfo(string && name, Grades && grades):mName(name),mGrades(grades){} 
}; 

unordered_map<int, StudentInfo> idsToStudentInfo; 

for(pair<int, string>& s : idsToNames) { 
    idsToStudentInfo.insert(
     make_pair(s.first, 
      StudentInfo(std::move(s.second),std::move(idsToGrades[s.first])) 
     ) 
    ); 
} 

대신 학년 벡터와 문자열 (문자 벡터)를 복사, 그들은 단지 매우 빠르다는 MNAME 문자열의 이동 생성자와 mGrades 문자열의 교환받을.

관련 문제