gpt4 book ai didi

c++ - std::vector 初始化元素的 move/复制构造函数

转载 作者:太空狗 更新时间:2023-10-29 23:35:59 26 4
gpt4 key购买 nike

我有这段代码:

#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 编译,没有标志的相同输出)

ctor
move ctor
dtor
dtor

现在不再使用 push_back 而是直接将 vector v 初始化为

vector<Foo> v{std::move(foo)};

我不明白为什么我得到输出:

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

在第一种情况下,为什么要调用复制构造函数?在第二种情况下,当编译器不执行省略时,我完全不知道为什么 move ctor 被调用两次。有任何想法吗?

最佳答案

vector<Foo> v{std::move(foo)};

在这里你调用了 vector 构造函数,它接受一个 std::initializer_list。 .初始化列表只允许 const访问它的元素,所以 vector将不得不从 initializer_list 复制每个元素到自己的存储。这就是导致调用复制构造函数的原因。

来自 §8.5.4/5 [dcl.init.list]

An object of type std::initializer_list<E> is constructed from an initializer list as if the implementation allocated a temporary array of N elements of type const E, where N is the number of elements in the initializer list.

另见 https://tristanbrindle.com/posts/beware-copies-initializer-list


至于额外的 move 构造函数调用 -fno-elide-constructors ,这在 another answer 中讨论过几天以前。似乎 g++ 对 initializer_list 的示例实现采用了一种非常直白的方法。显示在我上面引用的同一部分的标准中。

同样的例子,当compiled using clang , 不会产生额外的 move 构造函数调用。

关于c++ - std::vector 初始化元素的 move/复制构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24793019/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com