为什么std :: vector将其constness传递给包含的对象?

时间:2011-08-16 23:52:39

标签: c++ stl vector const

const int *int *const非常不同。与const std::auto_ptr<int>std::auto_ptr<const int>类似。但是,似乎没有const std::vector<int>std::vector<const int>的区别(实际上我不确定第二个是否允许)。这是为什么?

有时我有一个函数,我想传递一个向量的引用。该函数不应该修改向量本身(例如,没有push_back()),但是它想要修改每个包含的值(比如增加它们)。类似地,我可能想要一个函数只改变矢量结构但不修改它的任何现有内容(尽管这很奇怪)。使用std::auto_ptr(例如)可以做这种事情,但因为std::vector::front()(例如)被定义为

const T &front() const;
T &front();

而不仅仅是

T &front() const;

没有办法表达这一点。

我想做的例子:

//create a (non-modifiable) auto_ptr containing a (modifiable) int
const std::auto_ptr<int> a(new int(3));

//this works and makes sense - changing the value pointed to, not the pointer itself
*a = 4;
//this is an error, as it should be
a.reset();


//create a (non-modifiable) vector containing a (modifiable) int
const std::vector<int> v(1, 3);

//this makes sense to me but doesn't work - trying to change the value in the vector, not the vector itself
v.front() = 4;
//this is an error, as it should be
v.clear();

4 个答案:

答案 0 :(得分:7)

这是一个设计决定。

如果你有一个const容器,通常你不希望任何人修改它所包含的元素,这是它的一个固有部分。如果你愿意的话,容器完全“拥有”这些元素“巩固了联系”。

这与历史上更低级别的“容器”实现(即原始阵列)形成鲜明对比,后者更为放手。正如您所说,int const*int * const之间存在很大差异。但标准容器只是选择传递const

答案 1 :(得分:4)

区别在于指向int的指针不拥有它们指向的整数,而vector<int>确实拥有包含的整数。可以将vector<int>概念化为具有int成员的结构,其中成员的数量恰好是可变的。

如果你想创建一个可以修改向量中包含的值而不是向量本身的函数,那么你应该设计函数来接受迭代器参数。

示例:

void setAllToOne(std::vector<int>::iterator begin, std::vector<int>::iterator end)
{
    std::for_each(begin, end, [](int& elem) { elem = 1; });
}

如果您能够将所需的功能放在标题中,那么它可以通用为:

template<typename OutputIterator>
void setAllToOne(OutputIterator begin, OutputIterator end)
{
    typedef typename iterator_traits<OutputIterator>::reference ref;
    std::for_each(begin, end, [](ref elem) { elem = 1; });
}

答案 2 :(得分:1)

与你的建议语法相关的一个大问题是:std::vector<const T>std::vector<T>的类型不同。因此,如果没有某种转换,您无法将vector<T>传递给期望vector<const T>的函数。不是简单的演员,而是创建新的vector<const T>。那个新的不能简单地与旧的分享数据;它必须将数据从旧数据复制或移动到新数据。

您可以使用std::shared_ptr来解决此问题,但那是因为这些是共享指针。您可以有两个引用相同指针的对象,因此从std::shared_ptr<T>shared_ptr<const T>的转换不会受到影响(除了引用引用计数之外)。没有shared_vector

这样的东西

std::unique_ptr也有效,因为它们只能被移动,而不能复制。因此,只有其中一个会有指针。

所以你所要求的根本不可能。

答案 3 :(得分:1)

  • 你是对的,不可能有一个const int的向量主要是因为元素不可分配(对向量中包含的元素类型的要求)。
  • 如果你想要一个只修改向量元素但不向向量本身添加元素的函数,这主要是STL为你做的事情 - 有关于哪个容器包含一系列元素的函数是不可知的该函数只需要一对迭代器并对该序列执行其操作,完全忽略了它们包含在向量中的事实。
  • 查找“插入迭代器”以了解如何将某些东西插入容器而无需知道这些元素是什么。例如,back_inserter接受一个容器,它所关心的只是知道容器有一个名为“push_back”的成员函数。