一对向量构造函数:初始值设定项列表与显式构造
Pair of vector constructors: initializer list vs explicit construction
我以两种方式调用std::pair<vector<int>, int>
构造函数:
- 传入初始值设定项列表
- 传入显式向量(R 值)。
出于某种原因,初始值设定项列表版本会创建一个副本(并销毁一个)。
这是我的最小代码示例:
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()
。我不希望这种行为。有谁知道为什么?我也和叮当核对了一下。
问题来自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)
(带有U1 = std::initializer_list<int>
),而是(1)
1。因此,你需要构造一个临时std::vector<int>
,它作为const
引用传递给(1)
,它必须制作一个副本。
您可以通过以下任一方式凭经验确认这一点:
- 使用上面提到的第三个构造函数创建自己的
pair
— 在这种情况下,将选择(3)
,并移动临时vector
; - 在构造
std::pair
时显式构造std::initializer_list<int>
:
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
在 [temp.deduct.type]#5.6(2)
内处于非推导上下文中,因此演绎失败,这就是选择(1)
的原因。
相关文章:
- 一对向量构造函数:初始值设定项列表与显式构造
- 我使用向量来创建类对象列表.初始化向量时如何使用参数调用构造函数?
- 构造函数/函数声明参数列表中的统一初始化
- 在初始化列表之外手动调用基类的构造函数
- 采用初始值设定项列表的构造函数
- 提供初始值设定项列表构造函数的有效方法
- C 标准中是否有任何计划来解决初始化器列表构造函数的不一致性
- 接受迭代器的初始值设定项列表构造函数
- STD :: MAP初始化列表构造函数
- 如何避免丢失自动生成的初始化列表构造函数
- 如何最小化调用列表构造函数(复制构造函数)的次数?
- 初始化列表构造函数错误带有CRTP
- 启用默认初始值设定项列表构造函数
- 使用初始化列表构造函数时C++奇怪的行为
- 自定义列表类的初始值设定项列表构造函数
- 初始值设定项列表构造函数导致右值构造函数不明确
- 调用初始化列表构造函数的不同方式
- 为什么std::array不包含初始化列表构造函数
- C++ 为类模板提供初始值设定项列表构造函数
- 何时使用初始值设定项列表构造函数