C++ 为什么std::vector会将其常量传递给包含的对象?

C++ 为什么std::vector会将其常量传递给包含的对象?,c++,stl,vector,constants,C++,Stl,Vector,Constants,int*const和int*const非常不同。与const std::auto_ptrvs.std::auto_ptr类似。然而,const std::vector与std::vector之间似乎没有这样的区别(实际上,我甚至不确定第二个是允许的)。为什么会这样 有时我有一个函数,我想把一个引用传递给一个向量。函数不应该修改向量本身(例如nopush_back()),但它希望修改包含的每个值(比如,增加它们)。类似地,我可能希望函数只更改向量结构,而不修改其任何现有内容(尽管这很奇怪)。使用s

int*const
int*const
非常不同。与
const std::auto_ptr
vs.
std::auto_ptr
类似。然而,
const std::vector
std::vector
之间似乎没有这样的区别(实际上,我甚至不确定第二个是允许的)。为什么会这样

有时我有一个函数,我想把一个引用传递给一个向量。函数不应该修改向量本身(例如no
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();
//创建一个包含(可修改)int的(不可修改)自动\u ptr
const std::auto_ptr a(新int(3));
//这是可行的,也有意义——更改指向的值,而不是指针本身
*a=4;
//这是一个错误,应该如此
a、 重置();
//创建包含(可修改)int的(不可修改)向量
常数std::向量v(1,3);
//这对我来说是有意义的,但不起作用-试图改变向量中的值,而不是向量本身
v、 前()=4;
//这是一个错误,应该如此
v、 清除();

不同之处在于指向int的指针并不拥有它们所指向的int,而
向量则拥有包含的int。
vector
可以被概念化为具有int成员的结构,其中成员的数量恰好是可变的

如果要创建一个函数,该函数可以修改向量中包含的值,但不能修改向量本身,那么应该将该函数设计为接受迭代器参数

例如:

void setAllToOne(std::vector<int>::iterator begin, std::vector<int>::iterator end)
{
    std::for_each(begin, end, [](int& elem) { elem = 1; });
}
void setAllToOne(std::vector::iterator begin,std::vector::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; });
}
模板
void setAllToOne(输出迭代器开始、输出迭代器结束)
{
typedef typename迭代器_traits::reference;
std::对于每个元素(开始,结束,[](ref elem){elem=1;});
}

这是一项设计决策

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


这与历史上较低级别的“容器”实现(即原始阵列)形成对比,后者更易于操作。正如你所说的,在
int-const*
int-const
之间有很大的区别。但是标准容器只是选择传递
常量。

从语法上讲,您所建议的一个大问题是:
std::vector
std::vector
的类型不同。因此,如果不进行某种转换,就无法将
向量
传递给需要
向量
的函数。不是简单的强制转换,而是创建一个新的
向量
。新的不能简单地与旧的共享数据;它必须将数据从旧数据复制或移动到新数据

您可以使用
std::shared_ptr
,但这是因为这些是共享指针。您可以有两个引用同一指针的对象,因此从
std::shared_ptr
shared_ptr
的转换不会有任何影响(除了影响引用计数)。没有所谓的
共享向量

std::unique_ptr
也可以工作,因为它们只能从中移动,不能复制。因此,其中只有一个会有指针

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

  • 您是正确的,不可能有const int的向量,主要是因为元素不可赋值(对向量中包含的元素类型的要求)
  • 如果您想要一个只修改向量元素而不向向量本身添加元素的函数,这主要是STL为您所做的工作——函数不知道元素序列包含在哪个容器中。该函数只需要一对迭代器,并对该序列执行它的操作,完全忽略了它们包含在向量中的事实
  • 查阅“插入迭代器”,了解如何在不需要知道元素是什么的情况下将内容插入容器。例如,back_inserter接受一个容器,它只需要知道该容器有一个名为“push_back”的成员函数

我认为这是有道理的,我觉得奇怪的是,一些容器(为了这个问题我考虑代码< STD::AutoPyPTR <代码>容器),而其他人则不这样做。它似乎打破了“当有疑问的时候,要像内科医生那样做”的一般哲学。“卡鲁:如果你想考虑<代码> STD:AutoPPTR <代码>是一个容器,那就是你的选择……但这并不能改变事实,即它不是一个您不能有
std::vector
。元素类型必须是可复制构造和可赋值的。干杯,@Alf:我知道std::vector目前是如何工作的。提问者问为什么它不能以另一种方式工作,一种std::vector实际起作用的方式。最大的问题是缺少虚拟析构函数,这是我们不希望用于标准容器的(但如果您要设计您的容器,我猜是这样的)