通过const_cast修改const std :: vector <t>的元素

时间:2019-05-03 22:50:06

标签: c++ vector language-lawyer const-cast

以下程序是否具有未定义的行为?

#include <iostream>
#include <vector>

struct Foo
{
    const std::vector<int> x;
};

int main()
{
    std::vector<int> v = {1,2,3};
    auto f = new Foo{v};
    const_cast<int&>(f->x[1]) = 42; // Legal?
    std::cout << f->x[1] << "\n";
}

请注意,不是使用const_castf->x中删除常量,而是从f->x[x]中删除常量,该常量可能由单独的数组表示。还是允许翻译假设f->x[1]创建后是不可变的?

1 个答案:

答案 0 :(得分:1)

您的示例中没有未定义的行为。

上面的代码不会调用未定义的行为,因为基础数据(int)是可变的。让我们来看一个简单的例子。

#include <iostream>

struct IntPtr {
    int* data;
};

int main() {
    int a = 0;
    const IntPtr p { &a }; 
    *p.data = 10;
    std::cout << a; // Prints 10
}

所有这一切都是完全合法的,因为使IntPtr成为const会导致data是指向int的常量指针,而不是指向int常量的指针。我们可以修改p.data指向的数据;我们只是无法修改p.data本身。

const IntPtr p { &a };

*p.data = 10; // This is legal

int b;
p.data = &b; // This is illegal (can't modify const member)

那么该示例如何应用于std::vector 让我们添加索引到IntPtr的功能:

class IntPtr {
    int* data;
   public:
    IntPtr() = default;
    IntPtr(int size) : data(new int[size]) {}

    // Even though this is a const function we can return a mutable reference 
    // because the stuff data points to is still mutable. 
    int& operator[](int index) const {
        return data[index]; 
    }
};

int main() {
    const IntPtr i(100); 
    i[1] = 10; // This is fine
};

即使IntPtr是const,基础数据也是可变的,因为它是通过分配可变的int数组创建的。对于std::vector来说是相同的:基础数据仍然是可变的,因此const_cast是安全的。