c++ - 将列表传递到直接初始化时是否使用移动或复制构造函数?

标签 c++ initialization

给出以下玩具代码:

class P  // with compiler-generated copy constructor and move constructor
{
public:
    P(int x, int y) { }
};

int main()
{
    P p({x,y});
}

以我目前的理解,P p({x,y});中的{x,y}被转换为P类型的对象 通过隐式调用构造函数 P::P(int x, int y) 并将 xy 传递给它。通常会有优化,使得这个P对象直接构造为p。不过,我想问一下 P::P(int x, int y) 的隐式调用是由移动构造函数还是复制构造函数(由编译器生成)调用的?

最佳答案

Usually there is optimization so that this P object is directly constructed as p. Nevertheless, may I ask if this implicit call of P::P(int x, int y) is invoked by the move constructor or the copy constructor

让我们看看在 C++17 和 C++17 之前的版本中经过和不经过优化会发生什么。

C++17 之前的版本

在 C++17 之前,有 non-mandatory copy elision ,这意味着当你写:

P p({x,y}); //here a temporary of type X will be created and then moved/copied 

在上述语句中,在 C++17 之前,将创建一个 P 类型的临时对象,然后使用复制/移动构造函数对其进行复制/移动。也就是说,创建的临时文件将用于复制/移动构造p。由于在您的示例中,编译器将隐式生成移动构造函数,因此将使用它将代替隐式生成的复制构造函数,因为使用临时纯右值来构造 p。这是就像你写的:

P p(P{x, y}); //equivalent to what happens without optimization in prior C++17

请注意,编译器可以消除此复制/移动构造。因此,如果您想查看调用了哪些构造函数,则可以使用 -fno-elide-constructor 来禁用此非强制复制 elison。 output C++17 之前使用 -fno-elide-constructors 的程序是:

parameterized ctor
move ctor

同样,如果您不提供 -fno-elide-constructors 标志,那么编译器将忽略此移动构造,您将看到 output :

parameterized ctor

C++17 及以上版本

从 C++17 有 mandatory copy elision 。这意味着这里不会创建临时涉及。对象x将被直接构造就像你写的:

P p(x, y); //this is equivalent to what you wrote from C++17 due to mandatory copy elison

也就是说,从 C++17 开始,将不再创建 P 类型的临时对象。这意味着,标志 -fno-elide-constructors 在 C++17 的示例中将无效

我们保证不会从 C++17 调用复制/移动构造函数。

关于c++ - 将列表传递到直接初始化时是否使用移动或复制构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72477155/

相关文章:

c++ - 使用 xcode 的 ncurses.h 库中的 initscr() 函数错误

c++ - std::set_new_handler 如何提供更多可用内存?

java - 变量已初始化但已初始化时出错?

c++ - 双端队列 emplace_back 指向对象的新指针

c++ - 如果变量未初始化,Visual Studio 2017 不会生成任何警告?

c++ 为什么 const& 可以得到 const 值?

c++ - 头文件和多类用法(编辑 : forward declarations)

c++ - 如何在 C++ 中遍历句子中的单词?

c++ - 双括号初始化

c++ - 在 C++ 中分离声明和初始化