2014-01-23 3 views
-2

코드를 추출하여 아래 코드로 끝 냈습니다. 지도에 삽입 할 때 오류가 발생합니다 ...C++ 11의 동작 의미를 적용 할 때 컴파일러 오류가 발생했습니다.

질문을 표시 한 사람에게 감사드립니다. 답변을 먼저 보내 주시면 감사하겠습니다.)

진지하게 요점은 다음과 같습니다. 이동이 "최선의 노력"으로 이루어졌으며 사용이 보장되지 않는다는 사실 (여기에 순진한 삭제와 같이)은 많은 혼란을 야기합니다. 나에게 그것은 dodgy 중 하나는 컴파일러를 조용히하기 위해 결코 사용되지 않는 복사 생성자 몸체를 제공해야한다는 것이다.

물론 컴파일러와 제 stl 사이의 나쁜 플레이 일 수 있습니다. 살고 C + + 표준을 호흡 사람들을 떠나 명확하게.

#include <vector> 
#include <map> 
#include <iostream> 
using namespace std; 

struct FeedDataType 
{ 
    FeedDataType() {}; 
    FeedDataType(FeedDataType&&) = default; 

#if 0 
    // error: use of deleted function 'FeedDataType::FeedDataType(const FeedDataType&) - why? 
    FeedDataType(const FeedDataType&) = delete; 
#else 
    // Compiles ok but never called. But cannot mark it delete... 
    FeedDataType(const FeedDataType&) { cout << "Never called!" << endl; }; 
#endif 
}; 

int main() 
{ 
    vector<FeedDataType> x; 
    map<int, vector<FeedDataType> > mymap; 
    mymap.insert(std::make_pair(0, x)); 
} 

오류 :

In file included from /cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/vector:63:0, 
      from play3.cpp:1: 
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...) [with _T1 = FeedDataType; _Args = {const FeedDataType&}]': 
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_uninitialized.h:77:3: required from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const FeedDataType*, std::vector<FeedDataType> >; _ForwardIterator = FeedDataType*; bool _TrivialValueTypes = false]' 
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_uninitialized.h:119:41: required from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const FeedDataType*, std::vector<FeedDataType> >; _ForwardIterator = FeedDataType*]' 
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_uninitialized.h:260:63: required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<const FeedDataType*, std::vector<FeedDataType> >; _ForwardIterator = FeedDataType*; _Tp = FeedDataType]' 
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:310:9: required from 'std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = FeedDataType; _Alloc = std::allocator<FeedDataType>; std::vector<_Tp, _Alloc> = std::vector<FeedDataType>]' 
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_pair.h:137:64: required from 'constexpr std::pair<_T1, _T2>::pair(_U1&&, _U2&&) [with _U1 = int; _U2 = std::vector<FeedDataType>&; <template-parameter-2-3> = void; _T1 = int; _T2 = std::vector<FeedDataType>]' 
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_pair.h:273:72: required from 'constexpr std::pair<typename std::__decay_and_strip<_T1>::__type, typename std::__decay_and_strip<_T2>::__type> std::make_pair(_T1&&, _T2&&) [with _T1 = int; _T2 = std::vector<FeedDataType>&; typename std::__decay_and_strip<_T2>::__type = std::vector<FeedDataType>; typename std::__decay_and_strip<_T1>::__type = int]' 
play3.cpp:24:44: required from here 
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_construct.h:77:7: error: use of deleted function 'FeedDataType::FeedDataType(const FeedDataType&)' 
play3.cpp:13:9: error: declared here 

ORIGINAL POST :

내가 분명히하고 싶은 컴파일러 오류 (g ++ 레드햇에 4.7.2)가있다. 무엇이 중요합니까 : 단순히 이동 생성자 만 사용하려고합니다.

그래서 나는 쓰기 :

FeedDataType(FeedDataType&&) = default; 
FeedDataType(const FeedDataType&) = delete; 

아아, 그것은 (내가 당신에게 전체 스택 추적을 아끼지 것) 컴파일되지 않습니다 :

.../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_construct.h:77:7: error: use of deleted function 'FeedDataType::FeedDataType(const FeedDataType&)' 

복사의 ctor이 필요한 경우 명백한 것 아니, I 시체를 써서 프로그램 코어가 사용될 때 스택 추적을 살펴 봅니다.

FeedDataType(FeedDataType&&) = default; 
FeedDataType(const FeedDataType&) { cerr << "Called" << endl; assert(false); } 

글쎄, 프로그램이 컴파일됩니다. 사본 ctor 코드를 입력하지 않고 실행됩니다. 따라서, 사용하지 않으면, 왜 ctor를 삭제할 수 없습니까? 어떻게 사용하고 있는지 확인할 수 있습니까? 내가하지 않는

다른 점은 :

void FeedData::add(const FeedDataType & feedDataRow) 
{ 
    // Is move used here? If not why not warn? 
    some_vector.push_back(std::move(feedDataRow)); 
} 

이 분명히 복사 생성자를 사용합니다. 컴파일러에서 경고문/오류가 발생하여 작업을 이동하지 않았다면 좋았을 것입니까? 대형 프로그램에서는 const를 놓치기 쉽고 std :: move가 작업을 수행한다고 믿을 수 있습니다. 사실, 컴파일러 오류가 있어야합니다 - feedDataRow const, 이동 건설에서 가능해서는 안됩니다?

비 const 참조를 사용하면이 경우에 이동 생성자가 사용되면 더 좋아진 것처럼 보입니다. 아니면 가치로 여기를 지나야합니까?

제 생각에는 첫 번째 문제는 컴파일러 버그이지만, 무슨 일이 일어나고 있는지 아는 사람이 깨닫고 싶습니다. 나는 이동 의미가 쉽지만 분명히 숙제를해야한다고 생각했다. Mr. Meyers의 C++ 11 도서를 찾고 있습니다.)

감사합니다,

아드리안

+0

'표준 : 내가 값으로 저장 요소를 믿고 푸시가 다시 호출 될 때 내부적으로 복사 생성자를 사용 vector'. 지금 나는 당신이 그런 복사본을 피하기를 원한다고 추측하고 있지만 이것이 허용되는지 확실치 않습니다. 솔직히 말해서 저는이 분야의 C++ 11에 익숙하지 않습니다. – shuttle87

+0

우리를 구한 원래의 컴파일 타임 스택 추적이'FeedData :: add'를 가리 키지 않았습니까? –

+2

질문에 대답하지 않았습니까? const에서 이동하려고합니다. 이것은 가능하지 않으므로 복사가 대신 시도됩니다. 복사가 비활성화되어 컴파일 오류가 발생합니다. 지금까지 모든 것이 완전히 논리적으로 보입니다. 문제는 정확히 어디 있니? –

답변

1

Well, the program compiles and runs without entering the copy ctor code.
So, if not used, why cannot the copy ctor be deleted?
How can one be sure of what is being used?

는 다음 코드에서 사용

될 수있다 그것은 범위에있을 수 있습니다 : 우리는 전화를한다고 가정

void foo() = delete; 

void bar(bool b) 
{ 
    if (b) { foo(); } 
    // Other stuff 
} 

bar(false), foo은 호출되지 않지만 bar을 사용합니다. 어쨌든 삭제 된 기능. 오류 링크를 따라하는 경우

, 당신은 소스 복사 생성자의 일부가 사용될 수있는 볼 수 있습니다.

1

std::move 수단, 약, "당신은, 그렇지 않으면 복사 할 수 있습니다 이동하는 경우"(꽤 있지만,이 토론의 목적을 위해 충분히 가까이). 가능한 경우 이동하십시오. 그렇지 않으면 당황 할 것입니다. 이전의 의미론은 템플릿 기반 제네릭 구성 요소를 작성하는 거의 모든 상황을 포함하여 거의 모든 곳에서 유용합니다. 후자는 이동이 불가능할 수도 있고 복사가 가능할 수도있는 드문 경우에만 유용하지만 복사하고 싶지는 않습니다.

이 표준은 당신에게 전 의미하지만, 후자하지를 제공합니다. 당신이 후자를해야 할 경우, 당신은이 라인을 따라 자신을 작성할 수 있습니다

template< class T > 
typename std::remove_reference<T>::type&& my_move(T&& t) 
{ 
    return static_cast<typename std::remove_reference<T>::type&&>(t); 
} 

template< class T > 
typename std::remove_reference<T>::type&& my_move(const T& t) 
{ 
    static_assert(!std::is_lvalue_reference<T&>::value, "Move is requested, but only copying is possible"); 
} 
+0

알 겠어. 그런데 왜 try_move 또는 maybe_move라는 이름을 지정하지 않았습니까? 아니면 캐스트라고 해? 실제로 제거되지 않는 제거 알고리즘과 같이 자체적으로 이동하지는 않습니다. 왜 코드를 작성하려면 새로운 C++ 기능 + 표준 + 마이어스 책을 선택해야합니까? 나를 잘못 이해하지 마라. 나는 C++ 팬이고 사람들이 매뉴얼을 읽어야한다고 인정한다. 여기에 남겨 두자 ... 다른 한편으로, 나는 문제를 어디에 보여 주려고 내 게시물을 편집했다. 컴파일러를 조용히하기 위해 더미 본문을 추가해야하는 것처럼 보입니다. 그러나 "당신이 사용하지 않는 것에 대해 돈을 지불하지 않습니다"라는 원칙은 무엇입니까? 감사. –

1

복사 생성자는 std::make_pair에서 호출 std::pair의 생성자에 의해 사용되는 vector의 복사 생성자에 의해 사용됩니다. 작은 예제 프로그램의 주어진 실행에서 실제로 호출되지 않는 이유는 벡터가 비어 있다는 것입니다.

make_pair으로 전화하면 x에서 std::move을 시도하십시오.

+0

완벽한, 이것이 실제로 필요한 것입니다!make_pair에서 이동하면 깔끔하게 컴파일되지 않고 호출되지 않지만 필요한 Dummy Dummy Copy 생성자가 생깁니다. 이제 눈이 뜨면 평소와 같이 분명합니다. 감사! –

관련 문제