Namespaces
Variants

std:: addressof

From cppreference.net
Memory management library
( exposition only* )
Allocators
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Memory resources
Uninitialized storage (until C++20)
( until C++20* )
( until C++20* )
( until C++20* )

Garbage collector support (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
Определено в заголовочном файле <memory>
template < class T >
T * addressof ( T & arg ) noexcept ;
(1) (начиная с C++11)
(constexpr начиная с C++17)
template < class T >
const T * addressof ( const T && ) = delete ;
(2) (начиная с C++11)
1) Получает фактический адрес объекта или функции arg , даже при наличии перегруженного operator & .
2) Перегрузка rvalue удалена, чтобы предотвратить взятие адреса const rvalues.

Выражение std::addressof(e) является константным подвыражением , если e является lvalue константным подвыражением.

(начиная с C++17)

Содержание

Параметры

arg - lvalue объект или функция

Возвращаемое значение

Указатель на arg .

Возможная реализация

Приведенная ниже реализация не является constexpr , поскольку reinterpret_cast не может использоваться в константных выражениях. Требуется поддержка компилятора (см. ниже).

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;
}
**Примечание:** Весь код C++ внутри тегов `
` и `` был сохранен без изменений, как и требовалось. HTML-разметка и атрибуты также остались нетронутыми.

Корректная реализация этой функции требует поддержки компилятора: GNU libstdc++ , LLVM libc++ , Microsoft STL .

Примечания

Макрос тестирования возможностей Значение Стандарт Функция
__cpp_lib_addressof_constexpr 201603L (C++17) constexpr std::addressof

constexpr для addressof добавлен посредством LWG2296 , и MSVC STL применяет это изменение к режиму C++14 как отчёт о дефектах.

Существуют некоторые особые случаи, когда использование встроенного operator & является некорректным из-за поиска, зависимого от аргументов даже если он не перегружен, и вместо него может быть использован std::addressof .

template<class T>
struct holder { T t; };
struct incomp;
int main()
{
    holder<holder<incomp>*> x{};
    // &x; // ошибка: поиск, зависящий от аргументов, пытается инстанцировать holder<incomp>
    std::addressof(x); // OK
}

Пример

operator & может быть перегружен для класса-обертки указателя для получения указателя на указатель:

#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)
}

Возможный вывод:

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

Отчеты о дефектах

Следующие отчеты об изменениях в поведении, содержащие описания дефектов, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применяется к Поведение в опубликованной версии Корректное поведение
LWG 2598 C++11 std :: addressof < const T > мог брать адрес rvalues запрещено с помощью удаленной перегрузки

Смотрите также

аллокатор по умолчанию
(шаблон класса)
[static]
получает разыменовываемый указатель на свой аргумент
(публичная статическая функция-член std::pointer_traits<Ptr> )