何谓 name lookup
C++ 中很重要的一个概念:name lookup。
当编译器在遇到一个 name 的时候, 会做查找(lookup),会把引入这个 name 的声明和它关联起来,具体来说,又包含两种类型的 lookup:
- qualified lookup: 带限定的查找
- unqualified lookup:不带限定的查找
对于 std::cout << std::endl
,编译器做了这些 name lookup:
- 非限定查找,找到了
iostream
文件里的std
命名空间 - 限定查找,在
ostream
文件中找到了std::cout
变量的声明 - 限定查找,在
ostream
文件中找到了std::endl
函数 的定义
scope resolution operator
两个冒号挨着出现 ::
叫做 scope resolution operator, 中文意思是作用于解析操作符。
对于 name lookup:
- 如果 name 不出现在 scope resolution operator 右侧, 那么就是执行 unqualified lookup,即
<name>
或<name>::<blablabla>
的 name - 如果 name 出现在 scope resolution operator 右侧,那么就是 qualified lookup
具体规则又很多, 举一个最近遇到的:
class MemoryManager {
public:
...
void free(void *buffer) {
if (buffer_info.find(buffer) == buffer_info.end()) {
printf("Error: invalid address, not allocated from MemoryManager\n");
return;
}
allocated_size -= buffer_info[buffer];
buffer_info.erase(buffer);
::free(buffer); // 这一行使用了 scope resolution operator
}
};
为什么 MemoryManager::free()
内要使用 ::free()
而不是 free()
? 因为如果用 free()
会做 unqualified lookup,查询到当前函数本身,产生无限递归,这显然不是我们预期的。
Ref
https://en.cppreference.com/w/cpp/language/unqualified_lookup