const对象传染媒介给编译错误

时间:2013-06-26 06:33:21

标签: c++ stdvector c++98

我已在我的代码

中声明了以下内容
vector <const A> mylist; 

我收到以下编译错误 -

new_allocator.h:75: error: `const _Tp* __gnu_cxx::new_allocator<_Tp>::address(const _Tp&) const \[with _Tp = const A]' and `_Tp* __gnu_cxx::new_allocator<_Tp>::address(_Tp&) const [with _Tp = const A]' cannot be overloaded

但如果声明 -

vector <A> mylist;

我的代码编译。

在此上下文中是否不允许使用const?

我在这里复制我的代码供大家参考 -

#include <iostream>
#include <vector>

using namespace std;
class A
{
public:
    A () {cout << "default constructor\n";}
    A (int i): m(i) {cout << "non-default constructor\n";}

private:
    int m;
};

int main (void)
{
    vector<const A> mylist;

    mylist.push_back(1);

    return 0;
}

2 个答案:

答案 0 :(得分:31)

向量中的项目必须是可分配的(或者,在标准的更新版本中,可移动)。 const对象不可分配,因此尝试将它们存储在向量中将失败(或者至少可能失败 - 代码无效,但编译器无论如何都可以自由接受它,如果它这样选择,虽然大多数程序员通常更喜欢拒绝无效代码。)

我想真正的迂腐,如果你想要足够严重,你可以定义一个尽管是const可分配的类型,如下所示:

class ugly { 
    mutable int x;
public:
    ugly const &operator=(ugly const &u) const { 
        x = u.x;
        return *this;
    }
};

我相信你应该能够在vector中存储此类型的项目,即使它们是const。使用VC ++快速测试创建这些成功的向量。这与一些较旧的编译器(例如,使用g ++ 4.8.1失败)失败了,但是与最近合适的编译器一起工作(VC ++回到至少2015年,g ++回到至少5.4并且将++重新回到至少4.0 - 尽管我没有'我试图追踪支持它的每个版本的第一个版本。)

对于当前编译器,支持移动const对象的类型可能也可以正常工作。但是,以防万一不明显:即使标记为const,也允许您修改对象。这显然是对任何合理用户期望的直接违反,因此它主要是一个问题,而不是解决方案。

答案 1 :(得分:11)

使用push_back方法是个问题。 emplace_back将编译。 另一种选择(取决于你在这里没有描述的整个情况)如果插入的项目在向量之外有生命,则使用vector<A const&>。 向量中的项不需要是可赋值的,但如果不是,则不能使用某些成员函数和算法。

说明:

push_back应该首先默认 - 在向量中构造A,然后分配(使用copy-construct)给定的引用。这会破坏您的const资格,因此无法编译。

emplace_back使用“完美转发”来直接调用实际的构造函数。