Digamos que eu tenha uma classe parecida com esta (este é apenas um exemplo):
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; }
};
O const
construtor de cópia e a doNotChangeMyData
função fazem com que isso ptr
não possa ser alterado; no entanto, isso ainda me permite modificar o conteúdo da matriz apontada por ptr
.
Existe uma maneira de impedir que o conteúdo da ptr
matriz seja alterado const
apenas em instâncias, sem "ter cuidado" (ou mudar o ponteiro bruto)?
Eu sei que eu poderia fazer algo como
void doNotChangeMyData() const {
const double *const ptr = this->ptr;
ptr[43] = 14; // then this would fail to compile
}
Mas eu prefiro não ter que ...
std::vector
std::vector::operator[]()
pode modificar valores certo?vector
funcionaria.std::vector::operator[]() const
retorna umaconst
referênciaRespostas:
Ponteiros não se propagam
const
. Adicionandoconst
ao tipodouble*
yielddouble* const
, o que resulta em um não-valorconst
quando desreferenciado.Em vez disso, você pode usar um
std::vector
:a
std::array
:ou uma matriz incorporada (não recomendado):
Todas as três opções se propagam
const
.Se você realmente deseja usar ponteiros (fortemente não recomendado), use pelo menos a
std::unique_ptr
para evitar o gerenciamento manual de memória. Você pode usar ostd::experimental::propagate_const
wrapper nos fundamentos da biblioteca 2 TS:Ainda não está no padrão, mas muitos compiladores o suportam. Obviamente, essa abordagem é inferior aos contêineres adequados.
fonte
std::array
não funciona, se você não souber o tamanho no momento da compilação.vector
adiciona sobrecarga;unique_ptr
não adiciona sobrecarga, mas se o ponteiro precisar ser compartilhado, será necessárioshared_ptr
adicionar sobrecarga. Eu não acho que o VS suporta atualmentepropagate_const
(pelo menos o arquivo de cabeçalho referido por cppreference não existe com/std:c++latest
) :( #vector
TBH é geralmente superestimada, especialmente se comparada ao esforço do gerenciamento manual de memória. Além disso, se você compartilhar os ponteiros manualmente, precisará usar uma contagem de referência, para que a sobrecarga não seja peculiarshared_ptr
. Eu não sabia que o VS ainda não suportapropagate_const
(o GCC e o Clang suportam o IIRC), mas não é difícil criar o nosso de acordo com as especificações.vector
então pego seu conteúdo via.data()
ou&vec[0]
e trabalho diretamente com ele. No caso do compartilhado, geralmente tenho um proprietário do ponteiro que cria e exclui, mas outras classes compartilham os dados.