Actuellement, je me demande comment utiliser correctement un std::unique_ptr
en tant que variable membre concernant l'exactitude const.const correcte composition en utilisant std :: unique_ptr/std :: shared_ptr
L'exemple suivant permet de modifier le contenu appartenant à my_foo
en dépit est d'être const:
#include <iostream>
#include <memory>
struct foo {
foo() : value_ptr_(std::make_unique<int>(3)) {}
void increment() const {
++(*value_ptr_);
}
int get_value() const {
return *value_ptr_;
}
std::unique_ptr<int> value_ptr_;
};
int main() {
const foo my_foo;
std::cout << my_foo.get_value() << std::endl;
my_foo.increment(); // But my_foo is const!
std::cout << my_foo.get_value() << std::endl;
}
Remplacement std::make_unique<T>
avec std::make_unique<const T>
semble être une bonne solution au premier coup d'œil. Toutefois, ce n'autorise pas à modifier le contenu de my_foo
même si elle est non-const:
#include <iostream>
#include <memory>
struct foo {
foo() : value_ptr_(std::make_unique<int>(3)) {}
void increment() {
++(*value_ptr_);
}
int get_value() const {
return *value_ptr_;
}
std::unique_ptr<const int> value_ptr_;
};
int main() {
foo my_foo;
std::cout << my_foo.get_value() << std::endl;
my_foo.increment(); // compiler error
std::cout << my_foo.get_value() << std::endl;
}
Avoir un pointeur vers un int comme dans cet exemple minimal est bien sûr pas très significatif, mais dans le code réel du unique_ptr
pourrait tenir un pointeur vers une classe de base de quelque chose de polymorphe, c'est-à-dire un objet que nous ne pourrions pas simplement stocker par valeur.
Alors, comment cette situation peut-elle être mieux gérée?
Je ne sais pas pourquoi vous autorisez 'increment' à être appelé sur un objet' const foo'? Basé sur le nom, il ne devrait pas être autorisé à être appelé dans ce cas – UnholySheep
J'imagine de la même manière que ce que vous feriez avec un pointeur brut. Une sorte de classe d'emballage. – juanchopanza
Semble être ce que [std :: experimental :: propagate_const] (http://en.cppreference.com/w/cpp/experimental/propagate_const) est pour. Mais je n'ai pas assez de connaissances pour écrire une réponse. –