Address Of
cppreference C++ named requirements: CopyConstructible # Notes
Until C++11, classes that overloaded operator&
were not CopyConstructible and thus weren't usable in the standard library containers. As of C++11, the standard library uses std::addressof whenever the address of an object is needed.
More C++ Idioms/Address Of
NOTE:
addressof
可以看做是一个专门的用于获取object address的operator。获取object address不再使用&
,而是使用addressof
。
Intent
Find address of an object of a class that has an overloaded unary ampersand (&
) operator.
Motivation
C++ allows overloading of unary ampersand (&
) operator for class types. The return type of such an operator need not be the actual address of the object. Intentions(意图) of such a class are highly debatable but the language allows it nevertheless. Address-of idiom is a way to find the real address of an object irrespective(不考虑) of the overloaded unary ampersand(符号) operator and its access protection.
NOTE: 如果class已经overload了
&
运算符,并且这个overload&
不是获取地址的,那么此时就需要使用addressof
idiom。
In the example below, the main
function fails to compile because operator &
of nonaddressable
class is private. Even if it were accessible, a conversion from its return type double
to a pointer would not have been possible or meaningful.
class nonaddressable
{
public:
typedef double useless_type;
private:
useless_type operator&() const;
};
int main()
{
nonaddressable na;
nonaddressable * naptr = &na; // Compiler error here.
}
Solution and Sample Code
The Address-of idiom retrieves the address of an object using a series of casts.
#include<iostream>
class nonaddressable
{
public:
typedef double useless_type;
private:
useless_type operator&() const;
};
template <class T>
T * addressof(T & v)
{
return reinterpret_cast<T *>(& const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
}
int main()
{
nonaddressable na;
nonaddressable * naptr = addressof(na); // No more compiler error.
}
NOTE: 上述实现,采用的是interpretation model、aliasing、serialization的思路,它是实现是考虑的了较多问题:
1、
T
可能是CV的,它的最内层reinterpret_cast<const volatile char &>(v)
2、第二层使用
const_cast<char&>
去除CV,这就得到了binary representation3、
& const_cast<char&>
用于取binary representation的地址4、
reinterpret_cast<T *>
实现aliasing
C++11
In C++11 the template std::addressof, in the <memory>
header, was added to solve this problem. In C++17, the template is also constexpr
.