【发布时间】:2013-12-10 17:48:02
【问题描述】:
为什么当我用大括号初始化 std::vector 时
std::vector<TS> vec {ts1, ts2};
编译器调用两次复制构造操作符?另一方面 - 使用 push_back 它只调用一次。
#include <iostream>
#include <vector>
using namespace std;
struct TS{
TS(){
cout<<"default constructor\n";
}
TS(const TS &other) {
cout<<"Copy constructor\n";
}
TS(TS &&other) noexcept{
cout<<"Move constructor\n";
}
TS& operator=(TS const& other)
{
cout<<"Copy assigment\n";
return *this;
}
TS& operator=(TS const&& other) noexcept
{
cout<<"Move assigment\n";
return *this;
}
~TS(){
cout<<"destructor\n";
}
};
int main() {
TS ts1;
TS ts2;
cout<<"-----------------------------------------\n";
std::vector<TS> vec {ts1, ts2};
//vec.push_back(ts1);
//vec = {ts1, ts2};
cout<<"-----------------------------------------\n";
return 0;
}
【问题讨论】:
-
不应使用大括号初始化调用赋值运算符,但将参数复制到
std::initializer_list<TS>并复制出 => 每个参数调用两次复制构造函数。您可以将它们移入initializer_list(std::vector<TS> vec {std::move(ts1), std::move(ts2)};),但不能将它们移出,因此至少需要一个复制构造函数调用。 -
我至少可以强迫它使用移动分配,而不是应付吗?
-
不适用于列表初始化。但是,您可以编写一个变通方法,例如返回一个类型的函数,该类型将函数的参数存储为引用,并提供到
std::vector的转换,称为vector<TS> vec( collect_references(ts1, ts2) );。 -
@DyP 函数应该返回 std::vector。好的,好主意,谢谢。
-
不,因为现在不是
value_type。它应该返回一个带有template<class T> operator std::vector<T>() const的类型以推断value_typefor 要初始化的向量;然后它可以使用emplace_back并尽可能避免any copy-ctor。 Live example
标签: c++ stdvector curly-braces list-initialization