c++ - 为什么调用模棱两可的ctor时没有编译时错误?
问题描述
#include <iostream>
#include <vector>
int main()
{
auto v1 = std::vector<std::size_t>(std::size_t{8});
std::cout << v1.size() << std::endl;
auto v2 = std::vector<std::size_t>{std::size_t{8}};
std::cout << v2.size() << std::endl;
}
代码输出:
8
1
我知道这是 C++ 中的一个众所周知的问题,因为:
std::vector<std::size_t>(std::size_t{8})
来电
explicit vector(size_type count)
尽管
std::vector<std::size_t>{std::size_t{8}}
来电
vector(std::initializer_list<T> init, const Allocator& alloc = Allocator())
.
出乎我的意料:
为什么第二次调用不会因重载解析歧义而触发编译时错误?
在另一个相关问题中,一段类似的代码确实会触发歧义错误。
解决方案
因为没有歧义会导致错误。当我们使用列表初始化时,重载解决方案明显不同。它是故意分两个阶段完成的。
[over.match.list]
1当非聚合类类型 T 的对象被列表初始化([dcl.init.list])时,重载决议分两个阶段选择构造函数:
最初,候选函数是类 T 的初始化列表构造函数([dcl.init.list]),参数列表由初始化列表作为单个参数组成。
如果找不到可行的初始化列表构造函数,则再次执行重载决议,其中候选函数是类 T 的所有构造函数,参数列表由初始化列表的元素组成。
如果初始化列表没有元素并且 T 有默认构造函数,则省略第一阶段。在复制列表初始化中,如果选择了显式构造函数,则初始化格式错误。[注意:这与其他情况([over.match.ctor],[over.match.copy])不同,其中仅考虑转换构造函数进行复制初始化。仅当此初始化是重载决议的最终结果的一部分时,此限制才适用。——尾注]
第一步只 std::initializer_list
考虑构造函数。我们可以到达第二步,只有在第一次重载决议失败时才考虑其他构造函数。显然,重载决议不会找不到合适的std::initializer_list
构造函数。
您链接到的问题不是关于初始化向量的歧义。歧义在于选择函数重载。两者都是可行的,因为它们都接受一个不同的向量,该向量本身可以从同一个初始化列表中明确地初始化。
推荐阅读
- reactjs - 未捕获的错误:尝试在反应中呈现 html 时,对象作为 React 子项无效
- http-headers - 在 html 电子邮件中使用 img 标签来调用服务器端应用程序
- python - 带有列表的字典 - 根据键选择最好的
- sql - Excel Power Query - 排序/过滤表
- string - .Formula 中从范围到字符串
- video-streaming - 如何从任意点开始视频流 HTTP 直播
- vb.net - 如何使用 vb.net 将列表视图中的多行或记录或项目插入到 ms 访问
- vba - “ThisWorksheet”等价物?
- r - ggplot2:按顺序绘制多个向量
- php - PHP cURL 格式错误的 URL 问题