我将std::pair<vector<int>, int>
构造器称为两种方式:
出于某种原因,初始化器列表版本会进行复制(并销毁一个副本)。
这是我的最小代码示例:
auto dummy() {
return pair<vector<int>, int>{ {1,2,3,4,5}, 1};
}
auto dummy1() {
return pair<vector<int>, int>{ vector{1,2,3,4,5}, 1};
}
auto dummy2() {
return optional<vector<int> > { {1,2,3,4,5} };
}
检查编译器资源管理器后,我发现初始化器列表dummy()
版本调用了operator new
两次,并调用了delete
一次。既不使用显式构造版本dummy1()
也不使用中的类似std::optional
构造函数dummy2()
。我不会期望这种行为。有人知道为什么吗?我也检查了c。
问题来自std::pair
构造函数和模板参数推导/重载解析:
pair( const T1& x, const T2& y ); // (1)
template< class U1, class U2 >
pair( U1&& x, U2&& y ); // (2)
请注意,至少有一个“缺失”的构造函数:
pair( T1&& x, T2&& y ); // (3)
当对第一个参数使用列表初始化时,所选的构造函数不是(2)
(with U1 = std::initializer_list<int>
)而是(1)
1。因此,您需要构造一个临时的std::vector<int>
,它作为-的const
引用传递给(1)
,必须进行复制。
您可以通过以下任一方法凭经验确认:
pair
使用上述第三个构造函数创建自己的对象-在这种情况下,(3)
将选择临时对象vector
并将其移动;std::initializer_list<int>
while,构造std::pair
:pair<vector<int>, int>{ std::initializer_list<int>{1,2,3,4,5}, 1 };
另一方面,std::optional
作为单个模板构造函数:
template < class U = value_type >
constexpr optional( U&& value );
...但是有一个默认值U
,使该构造函数成为重载解析的有效候选者。
1调用时pair{ {1,2,3,4,5}, 1 }
,U1
在(2)
[temp.deduct.type]#5.6的非推论上下文中,因此推论失败,因此(1)
选择了为什么。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句