我想要创建一个const std::vector<T>,它可以存储用户代码可以访问但(不容易)修改的可更新值。这样做有几个好处。不能更改向量对象(但不能更改其内容)。因此,如果稍后有人决定添加新元素或其他可能导致悬空引用的操作,则可以在向量中建立对条目的引用,而不会有悬空的风险。而且,由于它将是一个完整的const对象,因此即使在没有UB和/或编译器抱怨的情况下也不能使用placement-new对其进行修改。
这似乎是可能的,因为虽然向量对象是const,但Ts不是而且必须存储为非const。试图将它们存储为const会产生以下错误:
C++标准禁止使用const元素的容器,因为
allocator<const T>格式不正确.
请参阅这
因此,由于T不是const,而只是在访问时才出现const,所以似乎可以通过使用const_cast来删除const来访问和更新它们。
我没有遇到这种可修改的const向量的使用,但它似乎是相当合法的。我是不是遗漏了什么?
下面是用于额外UB测试的代码,包括constexpr:
#include <vector>
#include <iostream>
constexpr int foo()
{
const std::vector<int> v{ 1,2,3 };
const int& rci = v[0]; // A const ref to v[0] is ok
int& ri = const_cast<int&>(v[0]); // A ref to v[0] as a non-const requires a cast
ri = 42; // v[0] is now 42;
return v[0];
}
void update_const_v(const std::vector<int>& v)
{
for (const int& i : v)
const_cast<int&>(i) = i + 1;
}
void print(const std::vector<int>& v)
{
for (auto& i:v)
std::cout << i << '\n';
std::cout << '\n';
}
int main()
{
const std::vector<int> v{ 1,2,3 };
const int& ri = v[0]; // A ref to v[0]
print(v);
update_const_v(v);
print(v);
std::cout << "Reference to first element of const vector: " << ri << '\n';
// Check for UB using constexpr
constexpr int i = foo();
return i;
}下面是在msvc、clang和gcc中运行。
发布于 2022-09-04 15:43:17
我所知道的std::vector的唯一可行的实现是使用指向T数组的指针,因为您的T是非const的,所以可以安全地修改对象,就像使用const std::unique_ptr<T[]>一样。
这并不能保证某人不能编写一个工作方式不同的std::向量实现,例如,它可以与编译器串通,将"const向量“数据放置到只读内存中。
因此,我认为您只剩下“它应该工作,而不是调用UB,除非一个平台做了一些非常不寻常的事情”。如果您想编写100%的便携代码,我不会做这个假设,但是对于大多数实际目的来说,如果有点奇怪的话,它似乎是有效的。
https://stackoverflow.com/questions/73596684
复制相似问题