gpt4 book ai didi

c++ - 使用函数的返回值初始化对象时不调用复制构造函数

转载 作者:可可西里 更新时间:2023-11-01 16:36:52 26 4
gpt4 key购买 nike

考虑以下代码:

#include <iostream>

using namespace std;

class A
{
public:
int a;
A(): a(5)
{
cout << "Constructor\n";
}
A(const A &b)
{
a = b.a;
cout << "Copy Constructor\n";
}
A fun(A a)
{
return a;
}
};

int main()
{
A a, c;
A b = a.fun(c);
return 0;
}

以上代码使用 g++ file.cpp 的输出是:

Constructor
Constructor
Copy Constructor
Copy Constructor

以上代码使用 g++ -fno-elide-constructors file.cpp 的输出是:

Constructor
Constructor
Copy Constructor
Copy Constructor
Copy Constructor

我知道返回值优化。我的问题是省略了对复制构造函数的调用(返回期间的临时对象或将返回的对象复制到 b)?

如果省略的复制构造函数是用于创建 b 的构造函数,那么 b 是如何创建的(因为在这种情况下也没有构造函数调用)?

如果我将行 A b = a.fun(c); 替换为 a.fun(c) 并使用第一种方法甚至第二种方法进行编译,然后复制构造函数也被调用 2 次。那么,如果在上一段中解释的情况下,临时对象的复制构造函数被省略了,那么为什么在这种情况下没有省略呢?

最佳答案

#include <iostream>

using namespace std;

class A
{
public:
int a;
A(): a(5)
{
cout << "Constructing: " << (void *)this << std::endl;
}
A(const A &b)
{
a = b.a;
cout << "Copy Constructor: " << (void *)this << " from " << (void *)&b << std::endl;
}
A fun(A a)
{
return a;
}
};

int main()
{

A a, c;
A b = a.fun(c);

std::cout << "a:" << (void *)&a << std::endl <<
"b:" << (void *)&b << std::endl <<
"c:" << (void *)&c << std::endl;
return 0;
}

产量:

Constructing: 0x7fffbb377220
Constructing: 0x7fffbb377210
Copy Constructor: 0x7fffbb377230 from 0x7fffbb377210
Copy Constructor: 0x7fffbb377200 from 0x7fffbb377230
a:0x7fffbb377220
b:0x7fffbb377200
c:0x7fffbb377210

于是构造a,构造c,将c复制到函数的中间(参数a ), 然后将中间体直接复制到 b 中,跳过 a 到返回中间体的典型复制。如果您按值传递(更改为 A fun(const A& a):

,则效果会更好
Constructing: 0x7fff8e9642b0
Constructing: 0x7fff8e9642a0
Copy Constructor: 0x7fff8e964290 from 0x7fff8e9642a0
a:0x7fff8e9642b0
b:0x7fff8e964290
c:0x7fff8e9642a0

a被构造,c被构造,c被直接复制到b,尽管b没有被传递给fun!

关于c++ - 使用函数的返回值初始化对象时不调用复制构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26937270/

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