Namespaces
Variants

launder

Depuis fr.cppreference.net
 
 
Bibliothèque d'utilitaires
Support langage
Support des types (types de base, RTTI)
Macros de fonctionnalité de bibliothèque (C++20)
Utilitaires de programme
Fonctions variadiques
Support des coroutines (C++20)
Support des contrats (C++26)
Comparaison à trois voies
(C++20)
(C++20)(C++20)(C++20)    
(C++20)(C++20)(C++20)

Utilitaires généraux
Opérateurs relationnels (obsolète en C++20)
Fonctions de comparaison d'entiers
(C++20)(C++20)(C++20)    
(C++20)
Opérations d'échange et de typeswap
exchange
declval
to_underlying
forward
forward_like
move_if_noexcept
as_const
Types de vocabulaire courants
pair
optional
variant
tuple_size
tuple_element
apply
make_from_tuple
expected
Bibliothèque de gestion mémoire



 
Allocateurs
allocator
allocation_result
scoped_allocator_adaptor
allocator_arg
uses_allocator
uses_allocator_construction_args
make_obj_using_allocator
pmr::polymorphic_allocator
uninitialized_construct_using_allocator
Ressources mémoire
pmr::memory_resource
pmr::get_default_resource
pmr::set_default_resource    
pmr::new_delete_resource
pmr::pool_options
pmr::null_memory_resource
pmr::synchronized_pool_resource
pmr::unsynchronized_pool_resource
pmr::monotonic_buffer_resource    
Gestion explicite de durée de vie

start_lifetime_as
start_lifetime_as_array
Types pour conception de classes composites
indirect
polymorphic
Divers
pointer_traits
to_address
addressof
align
assume_aligned
is_sufficiently_aligned
Bibliothèque C
malloc
free_aligned_sized
memalignment
Stockage non initialisé

( jusqu'en C++20*)raw_storage_iterator
(jusqu'en C++23) declare_reachable
declare_no_pointers
pointer_safety
undeclare_reachable
undeclare_no_pointers
get_pointer_safety
Algorithmes
spécialisés<memory>
Gestion mémoire de
bas niveau
operator new
bad_alloc
align_val_t
destroying_delete_t
launder
Pointeurs intelligents
unique_ptr
shared_ptr
weak_ptr
auto_ptr
jusqu'en C++17*)owner_less
owner_less
owner_hash
owner_equal
enable_shared_from_this
bad_weak_ptr
default_delete
out_ptr_t
inout_ptr_t
Gestion mémoire de bas niveau
 
 
(depuis C++17)<new>
template< class T >
constexpr T* launder( T* p ) noexcept;
Barrière de dévirtualisation par rapport à

. Retourne un pointeur vers un objet à la même adresse que celle représentée par p, tandis que l'objet peut être un nouveau sous-objet de classe de base dont la classe la plus dérivée est différente de celle de l'objet p d'origine. *pFormellement, étant donné

le pointeur

  • représente l'adresse p d'un octet en mémoireAun objet
  • est situé à l'adresse x est dans sa A
  • xdurée de viele type de
  • est le même que x, en ignorant les qualificateurs cv à chaque niveauTtout octet qui serait accessible via le résultat est accessible via p (les octets sont accessibles via un pointeur qui pointe vers un objet
  • si ces octets se trouvent dans le stockage d'un objet y qui est zinterconvertible par pointeur avec , ou dans le tableau immédiatement englobant dont y est un élément).zAlors

retourne une valeur de type std::launder(p) qui pointe vers l'objet T*. Sinon, le comportement est indéfini. xLe programme est mal formé si

est un type fonction ou T (éventuellement qualifié cv). void peut être utilisé dans une

std::launderexpression constante de base si et seulement si la valeur (convertie) de son argument peut être utilisée à la place de l'invocation de la fonction. En d'autres termes, n'atténue pas les restrictions dans l'évaluation constante. std::launderSujet à des restrictions sur l'échange

Notes

std::launder n'a aucun effet sur son argument. Sa valeur de retour doit être utilisée pour accéder à l'objet. Ainsi, il est toujours une erreur d'ignorer la valeur de retour.

Utilisations typiques de std::launder incluent :

  • Obtention d'un pointeur vers un objet créé dans le stockage d'un objet existant du même type, où les pointeurs vers l'ancien objet ne peuvent pas être réutilisés (par exemple, parce que l'un ou l'autre objet est un sous-objet de classe de base) ;
  • Obtention d'un pointeur vers un objet créé par un placement new à partir d'un pointeur vers un objet fournissant le stockage pour cet objet.

La restriction de reachability garantit que std::launder ne peut pas être utilisé pour accéder aux octets non accessibles via le pointeur original, interférant ainsi avec l'analyse d'échappement du compilateur.

int x[10];
auto p = std::launder(reinterpret_cast<int(*)[10]>(&x[0])); // OK
int x2[2][10];
auto p2 = std::launder(reinterpret_cast<int(*)[10]>(&x2[0][0]));
// Comportement indéfini : x2[1] serait accessible via le pointeur résultant vers x2[0]
// mais n'est pas accessible depuis la source
struct X { int a[10]; } x3, x4[2]; // disposition standard ; supposons aucun remplissage
auto p3 = std::launder(reinterpret_cast<int(*)[10]>(&x3.a[0])); // OK
auto p4 = std::launder(reinterpret_cast<int(*)[10]>(&x4[0].a[0]));
// Comportement indéfini : x4[1] serait accessible via le pointeur résultant vers x4[0].a
// (qui est interconvertible par pointeur avec x4[0]) mais n'est pas accessible depuis la source
struct Y { int a[10]; double y; } x5;
auto p5 = std::launder(reinterpret_cast<int(*)[10]>(&x5.a[0]));
// Comportement indéfini : x5.y serait accessible via le pointeur résultant vers x5.a
// mais n'est pas accessible depuis la source

Exemple

#include <cassert>
#include <cstddef>
#include <new>
struct Base
{
    virtual int transmogrify();
};
struct Derived : Base
{
    int transmogrify() override
    {
        new(this) Base;
        return 2;
    }
};
int Base::transmogrify()
{
    new(this) Derived;
    return 1;
}
static_assert(sizeof(Derived) == sizeof(Base));
int main()
{
    // Cas 1 : le nouvel objet n'a pas pu être remplacé de manière transparente car
    // il s'agit d'un sous-objet de base mais l'ancien objet est un objet complet.
    Base base;
    int n = base.transmogrify();
    // int m = base.transmogrify(); // comportement indéfini
    int m = std::launder(&base)->transmogrify(); // OK
    assert(m + n == 3);
    // Cas 2 : accès à un nouvel objet dont le stockage est fourni
    // par un tableau d'octets via un pointeur vers le tableau.
    struct Y { int z; };
    alignas(Y) std::byte s[sizeof(Y)];
    Y* q = new(&s) Y{2};
    const int f = reinterpret_cast<Y*>(&s)->z; // L'accès au membre de classe est un
                                               // comportement indéfini : reinterpret_cast<Y*>(&s)
                                               // a la valeur "pointeur vers s" et ne
                                               // pointe pas vers un objet Y
    const int g = q->z; // OK
    const int h = std::launder(reinterpret_cast<Y*>(&s))->z; // OK
    [](...){}(f, g, h); // produit l'effet [[maybe_unused]]
}

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Applicable à Comportement publié Comportement corrigé
LWG 2859 C++17 la définition de reachable ne prenait pas en compte l'arithmétique
des pointeurs depuis un objet pointer-interconvertible
inclus
LWG 3495 C++17 std::launder pourrait rendre un pointeur vers un membre
inactif déréférençable dans une expression constante
interdit