Скажем, у меня есть класс, который выглядит следующим образом (это только пример):
class A {
double *ptr;
public:
A() : ptr( new double[100] ) {}
A( const A &other ) {
other.ptr[7] = 15;
}
void doNotChangeMyData() const {
ptr[43] = 14;
}
void changeMyData() {
ptr[43] = 14;
}
~A() { delete[] ptr; }
};
И const
в конструкторе копирования, и в doNotChangeMyData
функции делают его таким, чтобы ptr
его нельзя было изменить; однако, это все еще позволяет мне изменять содержимое массива, на который указывает ptr
.
Есть ли способ предотвратить изменение содержимого ptr
массива только в const
экземплярах, за исключением «осторожности» (или отказа от необработанного указателя)?
Я знаю, что могу сделать что-то вроде
void doNotChangeMyData() const {
const double *const ptr = this->ptr;
ptr[43] = 14; // then this would fail to compile
}
Но я бы не хотел ...
std::vector
std::vector::operator[]()
можно изменить значения правильно?vector
будет работать.std::vector::operator[]() const
возвращаетconst
ссылкуОтветы:
Указатели не размножаются
const
. Добавлениеconst
к типуdouble*
приводитdouble* const
к появлениюconst
ненулевого значения при разыменовании.Вместо этого вы можете использовать
std::vector
:а
std::array
:или встроенный массив (не рекомендуется):
Все три варианта размножаются
const
.Если вы действительно хотите использовать указатели (настоятельно не рекомендуется), хотя бы используйте a,
std::unique_ptr
чтобы избежать ручного управления памятью. Вы можете использоватьstd::experimental::propagate_const
обертку из библиотеки основы 2 TS:Его пока нет в стандарте, но многие компиляторы его поддерживают. Конечно, этот подход уступает надлежащим контейнерам.
источник
std::array
не работает, если вы не знаете размер во время компиляции.vector
добавляет накладные расходы;unique_ptr
не добавляет накладных расходов, но если указатель должен использоваться совместно, то вам нужно,shared_ptr
что добавляет накладные расходы. Я не думаю, что VS в настоящее время поддерживаетpropagate_const
(по крайней мере, заголовочный файл, на который ссылается cppreference, не существует/std:c++latest
) :(vector
ТБХ часто завышаются, особенно по сравнению с ручным управлением памятью. Кроме того, если вы делитесь указателями вручную, вы должны использовать счетчик ссылок, так что накладные расходы не свойственныshared_ptr
. Я не знал, что VS еще не поддерживаетpropagate_const
(GCC и Clang поддерживают IIRC), но нетрудно развернуть нашу собственную согласно спецификации.vector
затем беру его содержимое через.data()
или&vec[0]
и работаю напрямую с этим. В случае общего доступа у меня часто есть один владелец указателя, который создает и удаляет, но другие классы совместно используют данные.