std:: addressof
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
定义于头文件
<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 起) |
|
若
e
是左值常量子表达式,则表达式
|
(C++17 起) |
目录 |
参数
| arg | - | 左值对象或函数 |
返回值
指向 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
对于
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); // 正常 }
示例
operator & 可为指针包装类重载以获取指向指针的指针:
#include <iostream> #include <memory> template<class T> struct Ptr { T* pad; // 添加填充以显示 'this' 与 '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); // 调用 int** 重载 f(std::addressof(p)); // 调用 Ptr<int>* 重载, (= this) }
可能的输出:
Ctor this = 0x7fff59ae6e88 int** overload called with p = 0x7fff59ae6e90 Ptr overload called with p = 0x7fff59ae6e88
缺陷报告
下列行为变更缺陷报告被追溯应用于先前发布的C++标准。
| 缺陷报告 | 应用于 | 发布时的行为 | 正确行为 |
|---|---|---|---|
| LWG 2598 | C++11 | std :: addressof < const T > 可能获取右值的地址 | 通过删除的重载禁止该操作 |
参见
|
默认分配器
(类模板) |
|
|
[static]
|
获取指向其参数的可解引用指针
(
std::pointer_traits<Ptr>
的公开静态成员函数)
|