Spec-Zone.ru › C++

std::addressof

Определено в заголовочном файле <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 rvalue.

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

(с C++17)

Параметры

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

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

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

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

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

// std::remove_reference is needed for explicitly specifying template arguments
// e.g. addressof<int&> and addressof<int&&> should behave same as addressof<int>
 
// overload for object types
template<class T>
typename std::enable_if<std::is_object<
    typename std::remove_reference<T>::type>::value, T*>::type addressof(T& arg) noexcept
{
    return reinterpret_cast<T*>(
               &const_cast<char&>(
                   reinterpret_cast<const volatile char&>(arg)));
}
 
// overload for function types
template<class T>
typename std::enable_if<!std::is_object<
    typename std::remove_reference<T>::type>::value, T*>::type addressof(T& arg) noexcept
{
    return &arg;
}

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

Примечания

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

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

Пример

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> мог получить адрес rvalue запрещено удалённой перегрузкой

См. также

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

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/memory/addressof

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API