std :: vector初始化移动/复制元素的构造函数 [英] std::vector initialization move/copy constructor of the element
问题描述
我有这段代码:
#include <iostream>
#include <vector>
using namespace std;
class Foo{
public:
Foo() noexcept {cout << "ctor" << endl;}
Foo(const Foo&) noexcept {cout << "copy ctor" << endl;}
Foo(Foo&&) noexcept {cout << "move ctor" << endl;}
Foo& operator=(Foo&&) noexcept {cout << "move assn" << endl; return *this;}
Foo& operator=(const Foo&) noexcept {cout << "copy assn" << endl; return *this;}
~Foo() noexcept {cout << "dtor" << endl;}
};
int main()
{
Foo foo;
vector<Foo> v;
v.push_back(std::move(foo));
// comment the above 2 lines and replace by
// vector<Foo> v{std::move(foo)};
}
输出是我期望的(用 g ++ -std = c ++ 11 --no-elide-constructors
,没有标志的相同输出)
The output is what I expect (compiled with g++ -std=c++11 --no-elide-constructors
, same output without the flag)
ctor
move ctor
dtor
dtor
使用 push_back
直接初始化向量 v
为
vector<Foo> v{std::move(foo)};
我不明白为什么得到输出:
I do not understand why I get the outputs:
1)(不含 - no-elide-constructors
)
ctor
move ctor
copy ctor
dtor
dtor
dtor
2)( - no-elide-constructors
)
ctor
move ctor
move ctor
copy ctor
dtor
dtor
dtor
dtor
在第一种情况下,为什么会调用copy ctor?在第二种情况下,当编译器不执行elision,我绝对不知道为什么move ctor被调用两次。有任何想法吗?
In the first case, why is the copy ctor invoked? And in the second case, when the compiler does not perform elision, I have absolutely no idea why the move ctor is invoked twice. Any ideas?
推荐答案
vector<Foo> v{std::move(foo)};
在这里你调用的矢量构造函数需要一个 std :: initializer_list
。初始化列表只允许 const
访问其元素,因此向量
将必须从 initializer_list
到其自己的存储。这是调用复制构造函数的原因。
Here you're calling the vector constructor that takes an std::initializer_list
. An initializer list only allows const
access to its elements, so the vector
is going to have to copy each element from the initializer_list
to its own storage. That's what causes the call to the copy constructor.
从§8.5.4/ 5 [dcl.init.list]
From §8.5.4/5 [dcl.init.list]
类型为
std :: initializer_list< E>
的对象是从初始化器列表构造的,实现分配了N
类型const E
的临时数组,其中N
是初始化器列表中的元素数。
An object of type
std::initializer_list<E>
is constructed from an initializer list as if the implementation allocated a temporary array ofN
elements of typeconst E
, whereN
is the number of elements in the initializer list.
对于 -fno-elide-constructors
的额外移动构造函数调用,这在另一个回答几天前。看起来好像g ++对于在上面引用的标准中的标准中显示的 initializer_list
的示例实现非常字面。
As for the extra move constructor call with -fno-elide-constructors
, this was discussed in another answer a couple of days ago. It seems as though g++ takes a very literal approach to the example implementation of an initializer_list
shown in the standard in same section I've quoted above.
同样的例子,当使用clang编译时, t产生额外的移动构造函数调用。
The same example, when compiled using clang, doesn't produce the extra move constructor call.
这篇关于std :: vector初始化移动/复制元素的构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!