Existe-t-il un moyen de faire la distinction entre un faible_ptr attribué (éventuellement expiré) et un non-affecté.
weak_ptr<int> w1;
weak_ptr<int> w2 = ...;
Je comprends les vérifications suivantes relatives à la non-affectation ou à l'expiration, mais existe-t-il une vérification (moins chère?) Uniquement pour la non-affectation?
if (!w.lock()) { /* either not assigned or expired */ }
Vous pouvez utiliser deux appels à owner_before
pour vérifier l’égalité avec un pointeur faible construit (vide) par défaut:
template <typename T>
bool is_uninitialized(std::weak_ptr<T> const& weak) {
using wt = std::weak_ptr<T>;
return !weak.owner_before(wt{}) && !wt{}.owner_before(weak);
}
Ceci ne renverra que true
si w{} "==" weak
, où "=="
compare le propriétaire, et selon en.cppreference.com :
L'ordre est tel que deux pointeurs intelligents ne se comparent comme équivalents que s'ils sont tous les deux vides ou s'ils possèdent le même objet, même si les valeurs des pointeurs obtenus par get () sont différentes (par exemple parce qu'ils pointent sur des sous-objets différents dans le même objet). objet).
Étant donné que le constructeur par défaut construit un pointeur {vide _ faible, il ne peut renvoyer true
que si weak
est également videNot retournera true
si weak
a expiré.
En regardant l'Assemblée générée (avec optimisation), cela semble plutôt optimisé:
bool is_uninitialized<int>(std::weak_ptr<int> const&):
cmp QWORD PTR [rdi+8], 0
sete al
ret
... comparé à la vérification de weak.expired()
:
bool check_expired(std::weak_ptr<int> const&):
mov rdx, QWORD PTR [rdi+8]
mov eax, 1
test rdx, rdx
je .L41
mov eax, DWORD PTR [rdx+8]
test eax, eax
sete al
.L41:
rep ret
... ou renvoie !weak.lock()
(~ 80 lignes d'assemblage).
Utiliser std :: faible_ptr :: expired ()
#include <iostream>
#include <memory>
//declare a weak pointer
std::weak_ptr<int> gw;
void f()
{
//check if expired
if (!gw.expired()) {
std::cout << "pointer is valid\n";
}
else {
std::cout << "pointer is expired\n";
}
}
int main()
{
f();
{
auto cre = std::make_shared<int>(89);
gw = cre;
f();
}
f();
}
Sortie
pointer is expired
pointer is valid
pointer is expired
Program ended with exit code: 0
Vous pouvez essayer de créer un pointeur partagé qui accepte un pointeur faible en tant que paramètre et lève une exception std :: bad_weak_ptr si un pointeur faible est arrivé à expiration (ou n’est pas affecté comme dans votre cas):
#include <memory>
#include <iostream>
int main(){
// with an assigned pointer
std::shared_ptr<int> p1(new int(42));
std::weak_ptr<int> w1(p1);
try {
std::shared_ptr<int> p2(w1);
}
catch (const std::bad_weak_ptr& e) {
std::cout << e.what() << '\n';
}
// with a non assigned pointer
std::shared_ptr<int> p2(new int(42));
std::weak_ptr<int> w2;
try {
std::shared_ptr<int> p2(w2); // raises an exception
}
catch (const std::bad_weak_ptr& e) {
std::cout << "Ptr 2: " << e.what() << '\n';
}
}