首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >const std::vector<T> w/o UB的修改内容

const std::vector<T> w/o UB的修改内容
EN

Stack Overflow用户
提问于 2022-09-04 03:53:37
回答 1查看 131关注 0票数 7

我想要创建一个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

代码语言:javascript
复制
#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中运行。

EN

回答 1

Stack Overflow用户

发布于 2022-09-04 15:43:17

我所知道的std::vector的唯一可行的实现是使用指向T数组的指针,因为您的T是非const的,所以可以安全地修改对象,就像使用const std::unique_ptr<T[]>一样。

这并不能保证某人不能编写一个工作方式不同的std::向量实现,例如,它可以与编译器串通,将"const向量“数据放置到只读内存中。

因此,我认为您只剩下“它应该工作,而不是调用UB,除非一个平台做了一些非常不寻常的事情”。如果您想编写100%的便携代码,我不会做这个假设,但是对于大多数实际目的来说,如果有点奇怪的话,它似乎是有效的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73596684

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档