我可以在向量中使用const来允许添加元素,但不能对已添加的元素进行修改吗?

60 c++ stl const

我对这个答案的评论让我思考了constness和sort的问题.我玩了一下,把我的问题减少到这个代码的事实:

#include <vector>

int main() {
    std::vector <const int> v;  
}
Run Code Online (Sandbox Code Playgroud)

不会编译 - 你不能创建const int的向量.显然,我应该知道这一点(而且我已经知道了),但我以前从未需要创造这样的东西.然而,它似乎对我来说是一个有用的构造,我想知道是否有任何解决这个问题的方法 - 我想将东西添加到向量(或其他),但是一旦添加它们就不应该被更改.

可能有一些令人尴尬的简单解决方案,但这是我以前从未考虑过的.我可能不应该提到排序(我可能会问另一个问题,看看这个问题的难度).我真正的基本用例是这样的:

vector <const int> v;     // ok (i.e. I want it to be OK)
v.push_back( 42 );        // ok
int n = v[0];             // ok
v[0] = 1;                 // not allowed
Run Code Online (Sandbox Code Playgroud)

ava*_*kar 22

好吧,在C++ 0x中你可以......

在C++ 03中,有一个段落23.1 [lib.containers.requirements]/3,它说

存储在这些组件中的对象类型必须满足CopyConstructible类型(20.1.3)的要求以及Assignable类型的附加要求.

这是目前阻止您const int作为类型参数使用的内容std::vector.

然而,在C++ 0X,本段中缺失,替代,T需要是Destructible与上额外的要求T是每个表达式指定,例如,v = ustd::vector仅当有效TMoveConstructibleMoveAssignable.

如果我正确地解释了这些要求,那么它应该可以实例化std::vector<const int>,你只会遗漏它的一些功能(我想这就是你想要的).您可以通过将一对迭代器传递给构造函数来填充它.我认为emplace_back()应该也可以,但我没有找到明确的要求T.

尽管如此,您仍然无法对矢量进行排序.


Jon*_*vis 17

放在标准容器中的类型必须是可复制和可分配的.auto_ptr造成这么多麻烦的原因正是因为它不遵循正常的复制和赋值语义.当然,任何const不可转让的东西.所以,你不能const在标准容器中粘贴任何东西.而如果元素不是const,那么你要能够改变它.

我认为最接近的解决方案是使用某种间接方式.因此,您可以拥有一个指向const的指针,或者您可以拥有一个保存所需值的对象,但该值不能在对象中更改(就像您Integer在Java中使用的那样).

使特定索引处的元素不可更改违背标准容器的工作方式.您可能能够以这种方式构建自己的工作,但标准工作则不然.除非您能够将初始化设置为{a, b, c}初始化语法,否则基于数组的任何数据都无法工作,因为一旦const创建了数组,就无法更改它.因此,vector无论您做什么,类都不可能使用const元素.

拥有const一个没有某种间接性的容器只是不能很好地工作.你基本上要求制作整个容器const- 如果你从已经初始化的容器中复制它就可以做到,但是你不能真正拥有容器 - 当然不是标准容器 - 它包含没有某种间接性的常量.

编辑:如果您要做的是主要是保持容器不变但仍然能够在代码中的某些位置更改它,然后在大多数地方使用const ref然后提供需要能够的代码更改容器直接访问或非const引用将使这成为可能.

因此,const vector<int>&在大多数地方使用,然后vector<int>&在需要更改容器的地方使用,或者让代码的那部分直接访问容器.这样,它几乎不可更改,但您可以在需要时更改它.

另一方面,如果您希望能够始终能够更改容器中的内容但不更改特定元素,那么我建议在容器周围放置一个包装类.在这种情况下vector,包装它并使下标操作符返回一个const ref而不是一个非const ref - 无论是那个还是副本.因此,假设您创建了一个模板化版本,您的下标运算符将如下所示:

const T& operator[](size_t i) const
{
    return _container[i];
}
Run Code Online (Sandbox Code Playgroud)

这样,您可以更新容器本身,但不能更改它的各个元素.只要你声明所有内联函数,它就不应该有很大的性能损失(如果有的话)使用包装器.


cHa*_*Hao 10

你不能创建const int的向量,即使你可以,它也没用.如果我删除第二个int,那么从那里开始的一切都向下移动 - 读取:修改 - 使得无法保证v [5]在两个不同的场合具有相同的值.

除此之外,在声明const之后不能将const赋值给它,而不是抛弃const.如果你想这样做,为什么你首先使用const?

  • 您可能需要考虑将向量设为const,然后在需要修改它时抛弃常量(并且知道您不会弄乱值).或者在向量周围包装你自己的类,并自己调节访问,因为你所说的不再是一个"向量",在STL意义上 - 它的一半功能消失了. (4认同)

Edw*_*nge 7

你需要编写自己的课程.您当然可以使用std :: vector作为内部实现.然后只需实现const接口和您需要的几个非const函数.