43

我在我的代码中声明了以下内容

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

2 回答 2

38

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

我想对于真正的迂腐的人来说,如果你想要的足够糟糕,你可以定义一个尽管是可分配的类型,const像这样:

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

我相信您应该能够将这种类型的项目存储在 a 中,vector即使它们是const. 使用 VC++ 创建这些向量的快速测试成功。这在一些较旧的编译器上失败了(例如,在 g++ 4.8.1 上失败了),但适用于最近的编译器(VC++ 至少回到 2015 年,g++ 至少回到 5.4,clang++ 至少回到 4.0——尽管我没有t 试图追踪每个支持它的第一个版本)。

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

于 2013-06-26T06:36:08.333 回答
6

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

解释 :

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

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

于 2013-06-26T11:09:36.507 回答