## addressof
### 头文件: `"boost/utility.hpp"`
要取得一个变量的地址,我们要依赖于返回的值是否真的是这个变量的地址。但是,技术上重载`operator&`是有可能的,这意味着存有恶意的人可以破坏你的地址相关的代码。`boost::addressof` 被用于获得变量的地址,不管取址操作符是否被误用。通过使用一些灵巧的内部机制,模板函数 `addressof` 确保可以获得真实的对象及其地址。
### 用法
为确保获得一个对象的真实地址,你要使用 `boost::addressof`. 它定义在 `"boost/utility.hpp"`. 它常用于原本要使用 `operator&` 的地方,它接受一个参数,该参数为要获得地址的那个对象的引用。
```
#include "boost/utility.hpp"
class some_class {};
int main() {
some_class s;
some_class* p=boost::addressof(s);
}
```
在进一步学习如何使用 `addressof`的细节前,了解一下`operator&`为何以及如何不一定会返回对象的地址是非常有用的。
### 快速了解一下存有恶意的人
如果你真的,真的,真的需要重载 `operator&`, 或者只是想试验一下操作符重载可能的用法,这的确很容易。当你重载 `operator&`时,它的语义肯定会与多数用户(以及函数!)所期望的不同,所以千万不要为了好玩而做这件事;除非有非常好的理由,否则不要去做它。以下有一段code-breaker代码:
```
class codebreaker {
public:
int operator&() const {
return 13;
}
};
```
对于这个类,任何人想获取一个`codebreaker`实例的地址都会得到一个不可思议的数字13.
```
template <typename T> void print_address(const T& t) {
std::cout << "Address: " << (&t) << '\n';
}
int main() {
codebreaker c;
print_address(c);
}
```
这不难做到,但是在实际的代码中这样做有没有好的理由?也许没有,因为除非是用在局部的类上,否则它是不安全的。原因是,虽然获取一个不完整类型的地址是合法的,但如果是要获取一个带有用户自定义`operator&`的不完整类型的地址则是未定义的行为。因为我们不能保证这不会发生,所以我们最好不要重载 `operator&`.
### 迅速的解决方法
即使一个类的 `operator&` 被重载了,也还是有办法获得这个类的实例的真实地址。`addressof` 使用了一些幕后的巧妙方法\[6\]来获得真实的地址,而不会受任何 `operator&` 的欺骗。如果你把函数(`print_address`)改为使用 `addressof`, 你就可以得到以下代码:
> \[6\] 非常出名的一种ingenious hack.
```
template <typename T> void print_address(const T& t) {
std::cout << "&t: " << (&t) << '\n';
std::cout << "addressof(t): " << boost::addressof(t) << '\n';
}
```
执行时,该函数将给出如下输出(或类似于以下的输出,因为准确的地址值取决于你的系统).
```
&t: 13
addressof(t): 0012FECB13
```
差不多就是这样了!如果有什么情况让你知道或怀疑一个类的`operator&`被重载了,而你又需要确保得到真实的地址(由于 `operator&` 被重载而变得不可信了), 你就应该使用 `addressof`.
### 总结
没有多少有力的论点支持重载 `operator&`,\[7\] 但由于这是可能的,总有些人会这样做。当你编写一些需要依赖于获得对象真实地址的代码时,`addressof` 可以帮助你确保得到真实的地址。在编写泛型代码时,没有办法知道将会操作什么类型,因此如果需要获取参数化类型的地址的话,就使用 `addressof`.
> \[7\] 即使是定制的硬件设备驱动程序
当你需要获得一个对象的真实地址时,使用 `addressof` ,不必管 `operator&` 的语义。
- 序
- 前言
- Acknowledgments
- 关于作者
- 本书的组织结构
- Boost的介绍
- 字符串及文本处理
- 数 据结构, 容器, 迭代器, 和算法
- 函数对象及高级编程
- 泛 型编程与模板元编程
- 数学及数字处理
- 输入/输出
- 杂项
- Part I: 通用库
- Library 1. Smart_ptr
- Smart_ptr库如何改进你的程序?
- 何时我们需要智能指针?
- Smart_ptr如何适应标准库?
- scoped_ptr
- scoped_array
- shared_ptr
- shared_array
- intrusive_ptr
- weak_ptr
- Smart_ptr总结
- Library 2. Conversion
- Conversion 库如何改进你的程序?
- polymorphic_cast
- polymorphic_downcast
- numeric_cast
- lexical_cast
- Conversion 总结
- Library 3. Utility
- Utility 库如何改进你的程序?
- BOOST_STATIC_ASSERT
- checked_delete
- noncopyable
- addressof
- enable_if
- Utility 总结
- Library 4. Operators
- Operators库如何改进你的程序?
- Operators
- 用法
- Operators 总结
- Library 5. Regex
- Regex库如何改进你的程序?
- Regex 如何适用于标准库?
- Regex
- 用法
- Regex 总结
- Part II: 容器及数据结构
- Library 6. Any
- Any 库如何改进你的程序?
- Any 如何适用于标准库?
- Any
- 用法
- Any 总结
- Library 7. Variant
- Variant 库如何改进你的程序?
- Variant 如何适用于标准库?
- Variant
- 用法
- Variant 总结
- Library 8. Tuple
- Tuple 库如何改进你的程序?
- Tuple 库如何适用于标准库?
- Tuple
- 用法
- Tuple 总结
- Part III: 函数对象与高级编程
- Library 9. Bind
- Bind 库如何改进你的程序?
- Bind 如何适用于标准库?
- Bind
- 用法
- Bind 总结
- Library 10. Lambda
- Lambda 库如何改进你的程序?
- Lambda 如何适用于标准库?
- Lambda
- 用法
- Lambda 总结
- Library 11. Function
- Function 库如何改进你的程序?
- Function 如何适用于标准库?
- Function
- 用 法
- Function 总结
- Library 12. Signals
- Signals 库如何改进你的程序?
- Signals 如何适用于标准库?
- Signals
- 用法
- Signals 总结