Namensräume
Varianten
Aktionen

std::addressof

Von cppreference.com
< cpp‎ | memory
 
 
Speicherverwaltungsbibliothek
(nur Exposition*)
Algorithmen für uninitialisierten Speicher
(C++17)
(C++17)
(C++17)
Beschränkte uninitialisierte
Speicher-Algorithmen
C-Bibliothek

Allocatoren
Speicherressourcen
Unterstützung für Garbage Collection
(C++11)(bis C++23)
(C++11)(bis C++23)
(C++11)(bis C++23)
(C++11)(bis C++23)
(C++11)(bis C++23)
(C++11)(bis C++23)
Uninitialisierter Speicher
Explizites Lebenszeitmanagement
 
Definiert in Header <memory>
template< class T >
T* addressof( T& arg ) noexcept;
(1) (seit C++11)
(constexpr seit C++17)
template< class T >
const T* addressof( const T&& ) = delete;
(2) (seit C++11)
1) Ermittelt die tatsächliche Adresse des Objekts oder der Funktion arg, auch bei überladenen operator&.
2) Die Rvalue-Überladung ist gelöscht, um zu verhindern, dass die Adresse von const Rvalues genommen wird.

Der Ausdruck std::addressof(e) ist ein konstantes Teilausdruck, wenn e ein lvalue konstantes Teilausdruck ist.

(seit C++17)

Inhalt

[edit] Parameter

arg - lvalue-Objekt oder -Funktion

[edit] Rückgabewert

Zeiger auf arg.

[edit] Mögliche Implementierung

Die untenstehende Implementierung ist nicht constexpr, da reinterpret_cast in einem konstanten Ausdruck nicht verwendet werden kann. Compiler-Unterstützung ist erforderlich (siehe unten).

template<class T>
typename std::enable_if<std::is_object<T>::value, T*>::type addressof(T& arg) noexcept
{
    return reinterpret_cast<T*>(
               &const_cast<char&>(
                   reinterpret_cast<const volatile char&>(arg)));
}
 
template<class T>
typename std::enable_if<!std::is_object<T>::value, T*>::type addressof(T& arg) noexcept
{
    return &arg;
}

Die korrekte Implementierung dieser Funktion erfordert Compiler-Unterstützung: GNU libstdc++, LLVM libc++, Microsoft STL.

[edit] Anmerkungen

Feature-Test-Makro Wert Std Feature
__cpp_lib_addressof_constexpr 201603L (C++17) constexpr std::addressof

constexpr für addressof wurde durch LWG2296 hinzugefügt, und MSVC STL wendet die Änderung als Fehlerbericht auf den C++14-Modus an.

Es gibt einige seltsame Fälle, in denen die Verwendung des integrierten operator& aufgrund von argumentabhängiger Auflösung schlecht formuliert ist, auch wenn er nicht überladen ist, und std::addressof stattdessen verwendet werden kann.

template<class T>
struct holder { T t; };
 
struct incomp;
 
int main()
{
    holder<holder<incomp>*> x{};
    // &x; // error: argument-dependent lookup attempts to instantiate holder<incomp>
    std::addressof(x); // OK
}

[edit] Beispiel

operator& kann für eine Wrapper-Klasse für Zeiger überladen werden, um einen Zeiger auf einen Zeiger zu erhalten

#include <iostream>
#include <memory>
 
template<class T>
struct Ptr
{
    T* pad; // add pad to show difference between 'this' and 'data'
    T* data;
    Ptr(T* arg) : pad(nullptr), data(arg)
    {
        std::cout << "Ctor this = " << this << '\n';
    }
 
    ~Ptr() { delete data; }
    T** operator&() { return &data; }
};
 
template<class T>
void f(Ptr<T>* p)
{
    std::cout << "Ptr   overload called with p = " << p << '\n';
}
 
void f(int** p)
{
    std::cout << "int** overload called with p = " << p << '\n';
}
 
int main()
{
    Ptr<int> p(new int(42));
    f(&p);                // calls int** overload
    f(std::addressof(p)); // calls Ptr<int>* overload, (= this)
}

Mögliche Ausgabe

Ctor this = 0x7fff59ae6e88
int** overload called with p = 0x7fff59ae6e90
Ptr   overload called with p = 0x7fff59ae6e88

[edit] Fehlerberichte

Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
LWG 2598 C++11 std::addressof<const T> konnte die Adresse von Rvalues nehmen durch eine gelöschte Überladung untersagt

[edit] Siehe auch

der Standard-Allocator
(Klassen-Template) [edit]
[static]
ermittelt einen dereferenzierbaren Zeiger auf sein Argument
(öffentliche statische Memberfunktion von std::pointer_traits<Ptr>) [edit]