简体   繁体   English

g ++ -std = c ++ 0x出现意外的编译问题

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

I have some compilation problems pushing back elements of type T to a vector when compiling with g++ -std=c++0x. 我有一些编译问题在使用g ++ -std = c ++ 0x进行编译时将类型T的元素推回到向量。

This is a minimal example: 这是一个最小的例子:

#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;
}

It compiles fine with g++ -Wall -pedantic, but it gives this error when compiling with g++ -Wall -pedantic -std=c++0x: 它使用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&)

So it seems that it doesn't find the right operator= of A. Why? 所以似乎找不到合适的算子= A.为什么? Why it states with _Iterator = A* when I'm passing A? 当我通过A时,为什么with _Iterator = A*

The Assignable requirement imposted by the language standard on the standard container elements requires the t = u expression to be valid even if u is a const object. 语言标准对标准容器元素所强加的可分配要求要求t = u表达式有效,即使u是const对象也是如此。 The requirement was defined that way since C++98 (see 23.1/4) 这个要求是从C ++ 98开始定义的(参见23.1 / 4)

You violated that requirement, since your assignment operator does not accept const objects. 您违反了该要求,因为您的赋值运算符不接受const对象。 This immediately mean that your class A cannot be used as a container element type. 这立即意味着您的A类不能用作容器元素类型。

Why it worked in C++03 is rather irrelevant. 为什么它在C ++ 03中起作用是相当无关紧要的。 It worked by accident. 它偶然起作用。 It is obvious from the error message that the C++0x implementation of the library uses some C++0x specific features (like std::move ), which is what makes the above requirement to come into play. 从错误消息中可以明显看出,库的C ++ 0x实现使用了一些C ++ 0x特定的功能(比如std::move ),这就是上述要求发挥作用的原因。 But anyway, a C++03 implementation (and even C++98 implementation) can also fail to compile for your A . 但无论如何,C ++ 03实现(甚至C ++ 98实现)也可能无法为您的A编译。

Your example with A c = a; 你的例子是A c = a; is irrelevant, since it does not use the assignment operator at all (why is it here?). 是无关紧要的,因为它根本不使用赋值运算符(为什么它在这里?)。

In order to fix the error you should either accept the parameter by const reference or by value. 为了修复错误,您应该通过const引用或值接受参数。

I'm quite sure this is a safety feature. 我很确定这是一个安全功能。 Types with a copy-assignment operator (or a copy constructor) that may mutate the right-hand side are not safe to use in standard containers - an example of this is (the now deprecated) std::auto_ptr which will break horribly if stored in a container. 用拷贝赋值运算符(或拷贝构造函数),可能发生变异右手边的类型是不是安全标准集装箱使用-这样的一个例子是(现在不建议使用) std::auto_ptr ,如果存储,这将打破可怕在一个容器中。

The old C++03 library implementation permitted such unsafe code, but apparently they implemented a compile-time check in the C++0x version -- probably in conjunction with move-enabling the containers. 旧的C ++ 03库实现允许这样不安全的代码,但显然他们在C ++ 0x版本中实现了编译时检查 - 可能与移动启用容器一起使用。

The standard's definition of copy-assignment operator is (section [class.copy] ): 标准的复制赋值运算符的定义是(section [class.copy] ):

A user-declared copy assignment operator X::operator= is a non-static non-template member function of class X with exactly one parameter of type X , X& , const X& , volatile X& or const volatile X& . 用户声明的复制赋值运算符X::operator=是类X的非静态非模板成员函数,其中只有一个参数类型为XX&const X&volatile X&const volatile X&

But the X& and volatile X& variants may not be compatible with containers assuming an assignment can be made from an r-value RHS. 但是X& volatile X&变体可能与容器不兼容,假设可以从r值RHS进行分配。

NOTE: Passing by value, eg X::operator=(X) is a fundamental part of the copy-and-swap idiom. 注意:按值传递,例如X::operator=(X)是复制和交换习惯用法的基本部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM