繁体   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