首页 > 解决方案 > 为什么 std::vector 不能保存常量对象?

问题描述

我不确定为什么不允许存在以下代码:

int main()
{
    std::vector<const int> v;
    v.reserve(2);
    v.emplace_back(100);
    v.emplace_back(200);
}

理论上,reserve()不构造任何东西,与resize(). 此外,emplace_back()正在构建“就地”对象,因此这些代码都没有覆盖已经构建的常量对象。

尽管如此,即使写第一行 ,std::vector<const int> v;也已经导致编译错误。为什么根本不允许有 a std::vectorof 常量?

标签: c++vectorconstants

解决方案


虽然最好在这里阅读“为什么”,但有一些简单的方法可以得到你想要的:

template<class T>
class as_const {
    T t;
public:
    as_const(T& t_): t(t_) {}
    as_const(const as_const&) = default;
    as_const(as_const &&) = delete;
    as_const& operator=(const as_const&) = default;
    as_const& operator=(as_const&&) = delete;

    operator const T&() const {
       return t;
    }
    const T& operator*() const { 
    // Or just a get method, anyway it's nicer to also have an explicit getter
       return t;
    }
};

std::vector<as_const<int>> vec;
vec.reserve(2)
vec.emplace_back(100);
vec.emplace_back(200);

如果您认为这对您的用例是合理的,您甚至可以决定您的包装器应该是“多么恒定”并提供移动构造函数(请注意,这t本身不是恒定的)。as_const

请注意,您不能以这种方式禁止重新分配向量。如果您想这样做(并且不想使用编译时大小的数组,因为您现在的大小仅在运行时),请查看std::unique_ptr<T[]>. 但请注意,在这种情况下,您首先必须创建一个可变变体,然后在 const 变体中重新安装它,因为底层数组已默认初始化,之后您无法更改任何内容。

当然,也有可能使用分配器并禁止重新分配。但这没有 stl 实现。这种行为有一些实现(我自己尝试过一次,但有点乱),但我不知道是否有任何提升。


推荐阅读