Lors d'un reset
, le nouvel objet commence par être construit avant de détruire le précédent. Si les objets ont une place importante en mémoire, il peut être intéressant de commencer par faire un reset()
avant de faire le reset(…)
.
#include <iostream> #include <memory> class A { public: A() { std::cout << "Constructor\n"; } ~A() { std::cout << "Destructor\n"; } }; int main() { std::shared_ptr<A> a = std::make_shared<A>(); a.reset(new A()); a = std::make_shared<A>(); }
Sortie :
Constructor Constructor Destructor Constructor Destructor Destructor
Il faut utiliser std::propagate_const<std::unique_ptr<X>>
.
Il existe aussi indirect_value
qui peut se substituer à std::propagate_const<std::unique_ptr<X>>
. Attention, indirect_value
ne permet pas de se substituer à std::propagate_const<std::shared_ptr<X>>
(voir Can I replace shared_ptr by indirect_value ? Archive du 04/08/2022 le 18/10/2022).
Soit la classe commune X
:
struct X { void g() const { std::cout << "g (const)\n"; } void g() { std::cout << "g (non-const)\n"; } };
et le programme commun :
int main() { Y y; y.f(); const Y cy; cy.f(); }
X
intégrée dans une classe Y
avec pointeur classiquestruct Y { Y() { } void f() const { std::cout << "f (const)\n"; m_ptrX.g(); } void f() { std::cout << "f (non-const)\n"; m_ptrX.g(); } // Ici, X est une instance sans pointeur. X m_ptrX; };
Rendu sans surprise :
f (non-const) g (non-const) f (const) g (const)
Si la méthode f const
est appelée, la méthode g const
est appelée également car une méthode const
ne peut pas appeler une méthode non const
.
struct Y { Y() : m_ptrX{} { } void f() const { std::cout << "f (const)\n"; m_ptrX->g(); } void f() { std::cout << "f (non-const)\n"; m_ptrX->g(); } std::unique_ptr<X> m_ptrX; };
Rendu :
f (non-const) g (non-const) f (const) g (non-const)
On ne respecte l'obligation d'appeler des méthodes const
depuis une méthode const
.
Prérequis : minimum clang 3.9, gcc 6.1. Pas dans Visual Studio 2017 sauf sur GitHub.
#include <experimental/propagate_const> std::experimental::propagate_const<std::unique_ptr<X>> m_ptrX;
Rendu :
f (non-const) g (non-const) f (const) g (const)
std::unique_ptr<FILE, decltype(&fclose)> fp(std::fopen(filename.c_str(), "r"), &fclose);
using custom deleter with unique_ptr Archive du 14/10/2014 le 28/12/2022
Il faut utiliser le comparateur owner_less
.
std::map<U, T, std::owner_less<U>> destination;
Sans passer par .lock()
pour empty()
.
#include <iostream> #include <memory> class A {}; int main() { { std::weak_ptr<A> aa; if (!aa.owner_before(std::weak_ptr<A>{}) && !std::weak_ptr<A>{}.owner_before(aa)) { std::cout << "empty1\n"; } if (aa.expired()) { std::cout << "expired1\n"; } } { std::shared_ptr<A> a; std::weak_ptr<A> aa = a; if (!aa.owner_before(std::weak_ptr<A>{}) && !std::weak_ptr<A>{}.owner_before(aa)) { std::cout << "empty2\n"; } if (aa.expired()) { std::cout << "expired2\n"; // False } } { std::weak_ptr<A> aa; { std::shared_ptr<A> a = std::make_shared<A>(); aa = a; if (!aa.owner_before(std::weak_ptr<A>{}) && !std::weak_ptr<A>{}.owner_before(aa)) { std::cout << "empty3\n"; // False } if (aa.expired()) { std::cout << "expired3\n"; // False } } if (!aa.owner_before(std::weak_ptr<A>{}) && !std::weak_ptr<A>{}.owner_before(aa)) { std::cout << "empty4\n"; // False } if (aa.expired()) { std::cout << "expired4\n"; } } return 0; }