gpt4 book ai didi

c++ - ADL的陷阱是什么?

转载 作者:IT老高 更新时间:2023-10-28 14:01:25 25 4
gpt4 key购买 nike

前段时间我读了一篇文章,解释了参数依赖查找的几个陷阱,但我再也找不到了。这是关于获得对你不应该访问的东西的访问权或类似的东西。所以我想我会在这里问:ADL 的陷阱是什么?

最佳答案

依赖于参数的查找存在很大的问题。例如,考虑以下实用程序:

#include <iostream>

namespace utility
{
template <typename T>
void print(T x)
{
std::cout << x << std::endl;
}

template <typename T>
void print_n(T x, unsigned n)
{
for (unsigned i = 0; i < n; ++i)
print(x);
}
}

这很简单,对吧?我们可以调用 print_n() 并将任何对象传递给它,它会调用 print 来打印对象 n 次。

其实,如果只看这段代码,我们完全不知道print_n会调用什么函数。它可能是这里给出的 print 函数模板,但也可能不是。为什么?依赖于参数的查找。

例如,假设您编写了一个类来表示 unicorn 。出于某种原因,您还定义了一个名为 print 的函数(多么巧合!),它只是通过写入一个取消引用的空指针而导致程序崩溃(谁知道您为什么这样做;那不是重要):

namespace my_stuff
{
struct unicorn { /* unicorn stuff goes here */ };

std::ostream& operator<<(std::ostream& os, unicorn x) { return os; }

// Don't ever call this! It just crashes! I don't know why I wrote it!
void print(unicorn) { *(int*)0 = 42; }
}

接下来,您编写一个小程序,创建一个 unicorn 并打印四次:

int main()
{
my_stuff::unicorn x;
utility::print_n(x, 4);
}

你编译这个程序,运行它,然后……它崩溃了。 “什么?!不可能,”你说:“我只是调用了 print_n,它调用了 print 函数来打印四次 unicorn !”是的,确实如此,但它没有调用您期望它调用的 print 函数。它被称为 my_stuff::print

为什么选择my_stuff::print?在名称查找期间,编译器发现调用 print 的参数是 unicorn 类型,这是在命名空间 my_stuff< 中声明的类类型

由于依赖于参数的查找,编译器在搜索名为 print 的候选函数时包含此命名空间。它找到 my_stuff::print,然后在重载决议期间将其选为最佳可行候选者:调用任一候选 print 函数和非模板函数都不需要转换首选函数模板,因此非模板函数 my_stuff::print 是最佳匹配。

(如果您不相信这一点,您可以按原样编译此问题中的代码并查看 ADL 的实际效果。)

是的,依赖于参数的查找是 C++ 的一个重要特性。它本质上是实现某些语言特性的所需行为,如重载运算符(考虑流库)。也就是说,它也非常非常有缺陷,可能会导致非常丑陋的问题。有几个建议来解决依赖于参数的查找,但没有一个被 C++ 标准委员会接受。

关于c++ - ADL的陷阱是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2958648/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com