tow*_*120 6 c++ curly-braces stdvector list-initialization
为什么当我用大括号初始化 std::vector 时
std::vector<TS> vec {ts1, ts2};
Run Code Online (Sandbox Code Playgroud)
编译器调用两次复制构造函数运算符?另一方面 - 使用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;
}
Run Code Online (Sandbox Code Playgroud)
小智 5
据我了解,initializer_lists 通过常量引用传递所有内容。从其中之一可能不安全move。initializer_list的构造函数vector复制每个元素。
以下是一些链接:\ ninitializer_list 和移动语义
\n\n\n\n\n\n\n不,这不会按预期工作;您仍然会得到副本。我对此感到非常惊讶,因为我认为初始化列表的存在是为了保留临时数组直到它们被移动。
\n\n初始化器列表的 begin 和 end 返回 const T *,因此代码中 \n move 的结果是 T const && \xe2\x80\x94 一个不可变的右值引用。无法有意义地移动这样的表达式。它将绑定到 T const & 类型的函数参数,因为右值确实绑定到 const\n 左值引用,并且您仍然会看到复制语义。
\n
\n\n\n\n\ninitializer_list 只提供对其元素的 const 访问。您可以使用 const_cast 来编译该代码,但随后的移动可能会导致未定义的行为(如果初始化器列表的元素确实是 const)。所以,不,这样做是不安全的。如果您确实需要的话,有\n解决方法。
\n
\n\n\n18.9 中的概要相当清楚地表明初始化器列表的元素始终通过 const 引用传递。不幸的是,在该语言的当前版本中,似乎没有任何方法可以在初始值设定项列表元素中使用移动语义。
\n
有关 std::initializer_list 设计的问题
\n\n\n\n\n来自 C++ 标准第 18.9 节:
\n\n类型initializer_list的对象提供对const E类型的对象数组的访问。[注意:一对指针或一个指针加上\na长度将是initializer_list的明显表示。\ninitializer_list用于实现指定的初始值设定项列表\ 8.5.4 中的 n。复制初始值设定项列表不会复制底层\n 元素。\xe2\x80\x94 尾注]
\n\n我认为大多数这些事情的原因是 std::initializer_list 实际上并不是一个容器。它没有值语义,它有指针语义。引用的最后一部分表明了这一点:复制初始值设定项列表不会复制底层元素。由于它们仅用于初始化事物的目的,因此我认为您无法获得更强大的容器(例如元组)的所有优点,这并不奇怪。
\n
如果我正确理解最后一部分,则意味着需要两组副本,因为(只有当您尝试使用 aninitializer_list不复制底层元素。initializer_list而不复制出元素时,前面的引用才有意义。)
std::initializer_list 的底层结构是什么?
\n\n\n\n\n不,您不能从初始化器列表的元素中移动,因为初始化器列表的元素应该是不可变的(请参阅上面引用的段落的第一句)。这也是为什么只有 const 限定的成员函数才能让您访问元素的原因。
\n
如果您愿意,您可以使用emplace_back:
vec.emplace_back(TS());\nvec.emplace_back(TS());\nvec.push_back(std::move(ts1));\nvec.push_back(std::move(ts2));\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
1663 次 |
| 最近记录: |