为什么当我使用大括号
初始化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;
}
答案 0 :(得分:2)
根据我的理解,initializer_list
通过const-reference传递所有内容。 move
可能不安全。 initializer_list
的{{1}}构造函数将复制每个元素。
以下是一些链接: initializer_list and move semantics
不,这不会按预期工作;你仍然会得到副本。我很漂亮 对此感到惊讶,因为我认为initializer_list存在 保留一系列临时工,直到他们搬家为止。
beginizer_list的开始和结束返回const T *,所以结果为 在你的代码中移动是T const&amp;&amp; - 不可变的右值引用。这样 表达不能有意义地移动。它将绑定到 T const&amp;类型的函数参数因为rvalues会绑定到const 左值引用,你仍然会看到复制语义。
Is it safe to move elements of a initializer list?
initializer_list仅提供对其元素的const访问。你可以 使用const_cast来编译代码,但随后移动可能会结束 未定义的行为(如果initializer_list的元素 是真正的const)。所以,做这个动作并不安全。有 如果你真的需要它,可以解决这个问题。
Can I list-initialize a vector of move-only type?
18.9的概要使其相当清楚 初始化列表的元素总是通过 常量引用。不幸的是,似乎没有任何方法 在当前的初始化列表元素中使用move-semantic 修订语言。
questions regarding the design of std::initializer_list
来自C ++标准的第18.9节:
类型为initializer_list的对象提供对const E类型对象数组的访问。[注意:一对指针或指针加上 长度将是initializer_list的明显表示。 initializer_list用于实现指定的初始化列表 在8.5.4。复制初始化列表不会复制基础 元素。 - 结束说明]
我认为大多数这些事情的原因是 std :: initializer_list实际上不是一个容器。它没有 值语义,它有指针语义。这是显而易见的 引用的最后一部分:复制初始化列表不会 复制基础元素。看来它们只是用于 初始化事物的目的,我不认为这是令人惊讶的 你没有得到更强大的容器的所有细节,如 元组。
如果我正确理解了最后一部分,则意味着需要两组副本,因为(之前的引用仅在您尝试时才有意义使用vector
不复制基础元素。initializer_list
而不复制元素。)
What is the underlying structure of std::initializer_list?
不,你不能从initializer_list的元素移动,因为 initializer_list的元素应该是不可变的(参见 上面引用的段落的第一句)。这也是原因 为什么只有const限定的成员函数才能让你访问 元件。
如果需要,可以使用initializer_list
:
emplace_back
答案 1 :(得分:1)
因为那里有两个元素。