为什么std::vector将其constness传递给所包含的对象
Why does std::vector transfer its constness to the contained objects?
A const int *
和A int *const
是非常不同的。同理,const std::auto_ptr<int>
vs. 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();
这是一个设计决策。
如果你有一个const
容器,你通常不希望任何人修改它所包含的元素,这是它的内在组成部分。容器完全"拥有"这些元素,可以说是"巩固了这种纽带"。
这与历史上更低级的"容器"实现(即原始数组)形成对比,后者更不受约束。正如你所说的,int const*
和int * const
之间有很大的区别。但是标准容器只是选择传递const
属性。
不同之处在于指向int的指针不拥有其所指向的整型,而vector<int>
拥有其所包含的整型。可以将vector<int>
定义为具有int成员的结构体,其中成员的数量恰好是可变的。
如果你想创建一个可以修改vector中包含的值但不能修改vector本身的函数,那么你应该设计这个函数来接受迭代器参数。
的例子:
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; });
}
您建议的一个大问题是:std::vector<const T>
与std::vector<T>
不是同一类型。因此,如果不进行某种转换,就不能将vector<T>
传递给需要vector<const T>
的函数。不是简单的cast,而是创建一个新的vector<const T>
。这个新系统不能简单地与旧系统共享数据;它必须复制或移动数据从旧的到新的。
您可以在std::shared_ptr
中解决这个问题,但这是因为它们是共享的指针。可以有两个对象引用同一个指针,因此从std::shared_ptr<T>
到shared_ptr<const T>
的转换不会造成损害(除了增加引用计数)。没有所谓的shared_vector
.
std::unique_ptr
也可以,因为它们只能移动,不能复制。因此,它们中只有一个会有指针。
所以你所要求的是根本不可能的
- 你是对的,不可能有const int类型的vector,主要是因为这些元素不能赋值(对vector中包含的元素类型的要求)。
- 如果你想要一个函数只修改vector的元素,而不向vector本身添加元素,这主要是STL为你做的——拥有不知道元素序列包含在哪个容器中的函数。该函数只是接受一对迭代器,并对该序列执行操作,完全忽略了它们包含在vector中的事实。
- 查找"插入迭代器"来了解如何在不知道元素是什么的情况下向容器插入内容。例如,back_inserter接受一个容器,它所关心的只是知道该容器有一个名为push_back的成员函数。
- 是否需要删除包含对象的"pair"?
- 如何在h文件中包含.o对象文件
- 指针数据类型变量如何包含对象?
- C++ 矢量不显示包含对象的数据
- 唯一 ptr 将所有权移动到包含对象的方法
- 通过引用返回包含对象的向量
- 仅在删除包含对象的向量时调用自定义»析构函数«
- QML中包含对象的QABSTRACTLISTMODEL的缺点
- std::list::merge() 对于包含对象的列表失败
- 从 std::aligned_union_t 获取指向包含对象的指针
- 通过QLIST迭代并在包含对象上调用函数
- 检查子对象的地址是否在包含对象的边界内是否合法
- std::vector 调用在重新分配时无论如何都包含对象的析构函数?
- C++ 如何获取对包含对象的引用
- 从包含对象指针的列表中删除
- 对于数据成员,如果包含对象已在动态内存中,则动态分配此变量(或不动态分配)之间是否有任何区别
- C++标准库容器相对于所包含对象的线程安全性
- 包含对象的结构的向量
- 包含对象的 C++ 结构
- 正在计算包含对象的此指针