我刚刚意识到这段代码编译得很好,但有未定义的行为,并且(自然(在运行时崩溃:
#include <map>
#include <memory>
#include <utility>
int main(int argc, char *argv[])
{
std::pair<std::unique_ptr<int>, int> a(&argc, 0);
std::map<std::unique_ptr<int>, int> m; m.insert(std::make_pair(&argc, argc));
}
这对我来说有点震惊,因为我只是自然地认为std::unique_ptr<T>
的T*
构造函数的explicit
特性会阻止我意外地将T *
转换为std::unique_ptr<T>
,但在一些转发给构造函数的包装器(如std::pair
(中,这种保护似乎不再起作用。
所以我想我想知道一些事情:
对此有很好的缓解措施吗?这是一个众所周知的问题吗?
这些是故意的,还是应该被视为标准中的缺陷?
如果这是一个缺陷,应该做什么纠正?它可以在库级别制作,还是需要更改语言?(例如,它是否需要
explicit
的过载能力?(
请记住,std::unique_ptr<int>
只是一个例子;代码错误并不总是显而易见的,而且代码模板化得越多,预测潜在危险的转换就变得越来越困难,所以我真的很想知道人们是如何处理的。
您正在调用std::pair<std::unique_ptr<int>, int>
的显式构造函数,它继承了std::unique_ptr<int>
的构造函数的显式性。
与std::unique_ptr<int> p(&argc);
基本相同。你必须对此保持警惕。
容器拥有它们的元素,insert
和emplace
必须构造值。insert
和emplace
不是构造函数或转换运算符,不能标记为explicit
。
必须在";并非偶然";以及";迟钝的故意做";。拥有转发构造函数(从C++20中有条件地显式(是委员会做出的选择。
Containers的emplace
方法就是最显著的例子;是的,这是意向性的。