3

我刚刚意识到这段代码编译得很好,但是在运行时有未定义的行为和(自然)崩溃:

#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));
}

这对我来说有点令人震惊,因为我很自然地假设'构造函数的explicit性质会阻止我意外地将 a 转换为,但似乎这种保护措施不再在一些转发给构造函数的包装器中起作用,例如.std::unique_ptr<T>T*T *std::unique_ptr<T>std::pair

所以我想我想知道一些事情:

  • 有没有很好的缓解方法?这是一个众所周知的问题吗?

  • 这些是故意的,还是应该被视为标准中的缺陷?

  • 如果是缺陷,应该进行哪些更正?可以在图书馆级别制作,还是需要更改语言?(例如,它是否需要explicit-ness 的可重载性?)

记住std::unique_ptr<int>只是一个例子;代码错误并不总是很明显,而且随着代码的模板化越多,预测潜在危险的转换就会变得越来越困难,所以我真的很想知道人们是如何处理这个问题的。

4

2 回答 2

1

您正在调用 的显式构造函数std::pair<std::unique_ptr<int>, int>,它从std::unique_ptr<int>的构造函数继承了它的显式性。

它与std::unique_ptr<int> p(&argc);. 你必须对此保持警惕。

容器拥有它们的元素,insert并且emplace必须构造值。insert并且emplace不是构造函数或转换运算符,它们不能被标记explicit

必须在“非偶然”和“迟钝刻意做”之间取得平衡。拥有转发构造函数(从 C++20 有条件地显式)是委员会做出的选择。

于 2021-03-19T12:03:23.970 回答
0

容器的emplace方法是这方面最显着的例子;是的,这是国际性的。

于 2021-03-19T12:03:00.933 回答