【问题标题】:Vector of const objects giving compile error给出编译错误的 const 对象的向量
【发布时间】:2013-06-23 04:17:04
【问题描述】:

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

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

【问题讨论】:

  • 你用的是什么编译器?这对我来说很好。
  • 您希望通过 const 项实现什么目标?
  • @petric - 我已经用 g++ (GCC) 3.4.3 编译了它
  • @underscore_d 使用 gcc 3.4.3 编译:不是 c++11。

标签: c++ stdvector c++98


【解决方案1】:

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

我想对于真正的迂腐的人来说,如果你想得够严重,你可以定义一个可分配的类型,尽管它是 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,clang++ 至少回到 4.0——尽管我没有t 试图追踪每个支持它的第一个版本)。

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

【讨论】:

  • 实际上您可以在不可分配的项目上使用向量。只是你不能使用很多成员函数/算法,比如 push_back。
  • @lip:在某些情况下,您也许可以侥幸逃脱,但我相信在每种情况下,标准中的要求是 T 必须是 MoveAssignable 或 CopyAssignable。
  • 我们刚刚遇到了同样的问题。该代码在 VC++ (2012) 中编译并运行良好,但 g++ 4.8.2 和 clang 3.4 都不喜欢它。
  • “向量中的项必须是可赋值的”来自 C++03; C++11 放宽了这一要求。 (但是,在 C++11 上是否允许 const 对象的向量并不完全清楚;请参阅 here
  • const-ness of a variable 意味着该变量一旦分配就不能更改。所以,我不明白:为什么不想将永远不应该在向量中更改一次的对象放入向量中?我也不明白为什么 push_back 不应该工作。
【解决方案2】:

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

说明:

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

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

【讨论】:

  • 一般正确,但emplace_back 不使用对象的移动构造函数。它使用“完美转发”直接就地调用实际的构造函数。请参阅(例如)en.cppreference.com/w/cpp/container/vector/emplace_back
  • 我认为容器也不允许存储引用(或者至少不是vectorvector&lt;A const&amp;&gt; 不能编译
  • 容器不能存储引用。这到底是怎么得到 7 票的?
猜你喜欢
  • 2018-03-16
  • 2011-01-20
  • 1970-01-01
  • 2014-10-28
  • 1970-01-01
  • 1970-01-01
  • 2017-03-27
  • 2023-03-26
  • 1970-01-01
相关资源
最近更新 更多