簡體   English   中英

g ++ -std = c ++ 0x出現意外的編譯問題

[英]Unexpected compilation problem with g++ -std=c++0x

我有一些編譯問題在使用g ++ -std = c ++ 0x進行編譯時將類型T的元素推回到向量。

這是一個最小的例子:

#include <vector>

using namespace std;

class A {
public:
    A() { }

    A& operator=(A &orig) {
        return *this;
    }
};

int main(int argc, char **argv) {
    A a;
    vector<A> b;
    A c = a; // This is fine
    b.push_back(a); // This is not, but only when compiling with -std=c++0x!
    return 0;
}

它使用g ++ -Wall -pedantic編譯得很好,但是在使用g ++ -Wall -pedantic -std = c ++ 0x進行編譯時會出現此錯誤:

 In file included from /usr/include/c++/4.4/vector:69,
                 from min.cpp:1:
/usr/include/c++/4.4/bits/vector.tcc: In member function ‘void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, _Args&& ...) [with _Args = const A&, _Tp = A, _Alloc = std::allocator<A>]’:
/usr/include/c++/4.4/bits/stl_vector.h:741:   instantiated from ‘void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = A, _Alloc = std::allocator<A>]’
min.cpp:20:   instantiated from here
/usr/include/c++/4.4/bits/vector.tcc:314: error: no match for ‘operator=’ in ‘__position.__gnu_cxx::__normal_iterator<_Iterator, _Container>::operator* [with _Iterator = A*, _Container = std::vector<A, std::allocator<A> >]() = ((const A&)((const A*)std::forward [with _Tp = const A&](((const A&)((const A*)__args#0)))))’
min.cpp:11: note: candidates are: A& A::operator=(A&)
In file included from /usr/include/c++/4.4/vector:61,
                 from min.cpp:1:
/usr/include/c++/4.4/bits/stl_algobase.h: In static member function ‘static _BI2 std::__copy_move_backward<true, false, std::random_access_iterator_tag>::__copy_move_b(_BI1, _BI1, _BI2) [with _BI1 = A*, _BI2 = A*]’:
/usr/include/c++/4.4/bits/stl_algobase.h:595:   instantiated from ‘_BI2 std::__copy_move_backward_a(_BI1, _BI1, _BI2) [with bool _IsMove = true, _BI1 = A*, _BI2 = A*]’
/usr/include/c++/4.4/bits/stl_algobase.h:605:   instantiated from ‘_BI2 std::__copy_move_backward_a2(_BI1, _BI1, _BI2) [with bool _IsMove = true, _BI1 = A*, _BI2 = A*]’
/usr/include/c++/4.4/bits/stl_algobase.h:676:   instantiated from ‘_BI2 std::move_backward(_BI1, _BI1, _BI2) [with _BI1 = A*, _BI2 = A*]’
/usr/include/c++/4.4/bits/vector.tcc:308:   instantiated from ‘void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, _Args&& ...) [with _Args = const A&, _Tp = A, _Alloc = std::allocator<A>]’
/usr/include/c++/4.4/bits/stl_vector.h:741:   instantiated from ‘void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = A, _Alloc = std::allocator<A>]’
min.cpp:20:   instantiated from here
/usr/include/c++/4.4/bits/stl_algobase.h:561: error: no match for ‘operator=’ in ‘* -- __result = std::move [with _Tp = A&](((A&)(-- __last)))’
min.cpp:11: note: candidates are: A& A::operator=(A&)

所以似乎找不到合適的算子= A.為什么? 當我通過A時,為什么with _Iterator = A*

語言標准對標准容器元素所強加的可分配要求要求t = u表達式有效,即使u是const對象也是如此。 這個要求是從C ++ 98開始定義的(參見23.1 / 4)

您違反了該要求,因為您的賦值運算符不接受const對象。 這立即意味着您的A類不能用作容器元素類型。

為什么它在C ++ 03中起作用是相當無關緊要的。 它偶然起作用。 從錯誤消息中可以明顯看出,庫的C ++ 0x實現使用了一些C ++ 0x特定的功能(比如std::move ),這就是上述要求發揮作用的原因。 但無論如何,C ++ 03實現(甚至C ++ 98實現)也可能無法為您的A編譯。

你的例子是A c = a; 是無關緊要的,因為它根本不使用賦值運算符(為什么它在這里?)。

為了修復錯誤,您應該通過const引用或值接受參數。

我很確定這是一個安全功能。 用拷貝賦值運算符(或拷貝構造函數),可能發生變異右手邊的類型是不是安全標准集裝箱使用-這樣的一個例子是(現在不建議使用) std::auto_ptr ,如果存儲,這將打破可怕在一個容器中。

舊的C ++ 03庫實現允許這樣不安全的代碼,但顯然他們在C ++ 0x版本中實現了編譯時檢查 - 可能與移動啟用容器一起使用。

標准的復制賦值運算符的定義是(section [class.copy] ):

用戶聲明的復制賦值運算符X::operator=是類X的非靜態非模板成員函數,其中只有一個參數類型為XX&const X&volatile X&const volatile X&

但是X& volatile X&變體可能與容器不兼容,假設可以從r值RHS進行分配。

注意:按值傳遞,例如X::operator=(X)是復制和交換習慣用法的基本部分。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM