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부터)
(C++17부터 constexpr)
template < class T >
const T * addressof ( const T && ) = delete ;
(2) (C++11부터)
1) 오버로드된 operator & 가 존재하는 경우에도 객체나 함수 arg 의 실제 주소를 획득합니다.
2) Rvalue 오버로드가 삭제되어 const rvalue의 주소를 취하는 것을 방지합니다.

표현식 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;
}

이 함수의 올바른 구현을 위해서는 컴파일러 지원이 필요합니다: GNU libstdc++ , LLVM libc++ , Microsoft STL .

참고 사항

기능 테스트 매크로 표준 기능
__cpp_lib_addressof_constexpr 201603L (C++17) constexpr std::addressof

constexpr for addressof LWG2296 에 의해 추가되었으며, MSVC STL은 이 변경 사항을 결함 보고서로써 C++14 모드에 적용합니다.

내장 operator & 사용이 오버로드되지 않았음에도 인수 종속 lookup 때문에 형식에 맞지 않는 이상한 경우들이 있으며, 이때 std::addressof 를 대신 사용할 수 있습니다.

template<class T>
struct holder { T t; };
struct incomp;
int main()
{
    holder<holder<incomp>*> x{};
    // &x; // 오류: 인수 종속 조회가 holder<incomp>의 인스턴스화를 시도함
    std::addressof(x); // 정상
}

예제

operator & 는 포인터 래퍼 클래스에 대해 오버로드되어 포인터에 대한 포인터를 얻을 수 있습니다:

#include <iostream>
#include <memory>
template<class T>
struct Ptr
{
    T* pad; // 'this'와 'data'의 차이를 보여주기 위해 pad 추가
    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);                // int** 오버로드 호출
    f(std::addressof(p)); // Ptr<int>* 오버로드 호출, (= 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 > 우측값의 주소를 취할 수 있었음 삭제된 오버로드로 금지됨

참고 항목

기본 할당자
(클래스 템플릿)
[static]
인수에 대한 역참조 가능한 포인터를 얻음
( std::pointer_traits<Ptr> 의 public static 멤버 함수)