gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 10:26:48 25 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

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

最佳答案

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

在这里,您将调用采用 std::initializer_list的 vector 构造函数。初始化列表仅允许 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.



至于用 -fno-elide-constructors进行的额外的move构造函数调用,几天前在 another answer中对此进行了讨论。好像g++对上面我在同一部分中的标准中显示的 initializer_list的示例实现采取了非常直观的方法。

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

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

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