Модифицирующий элемент const std :: vector <T>через const_cast - PullRequest
10 голосов
/ 04 мая 2019

Имеет ли следующая программа неопределенное поведение?

#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_cast для удаления константы из f->x, а вместо этого исключает константу из f->x[x], которая предположительно представлена ​​отдельным массивом. Или перевод допускает, что f->x[1] является неизменным после его создания?

1 Ответ

1 голос
/ 04 мая 2019

В вашем примере нет неопределенного поведения.

Приведенный выше код не вызывает неопределенное поведение, поскольку базовые данные (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 является константой, базовые данные являются изменяемыми , потому что они создаются путем выделения массива изменяемых целых чисел.То же самое для std::vector: лежащие в основе данные все еще являются изменяемыми, поэтому безопасно const_cast их хранить.

...