有人可以解释这个 c++ 程序的输出吗?

Can someone explain the output of this c++ program?

本文关键字:程序 输出 c++ 解释      更新时间:2023-10-16

为什么输出foo3等于3? 我建议,当调用bar(foo1)时,函数bar在堆栈上创建foo1的副本,因此它的值等于 0,当返回此值时,foo3的复制构造函数再次递增该值,所以它应该是 2?

提前谢谢。

这是我的代码:

#include <iostream>
struct Foo {
Foo()
: x(0)
{
}
Foo(const Foo& foo)
: x(foo.x + 1)
{
}
int x;
};
Foo bar(Foo foo)
{
foo.x++;
return foo;
}
int main()
{
Foo foo1;
Foo foo2 = foo1;
std::cout << "A:" << foo1.x << std::endl;
std::cout << "B:" << foo2.x << std::endl;
Foo foo3 = bar(foo1);
std::cout << "C:" << foo3.x << std::endl;
}

输出:

A:0
B:1
C:3

我相信这里有三个复制构造函数在工作,行foo2 = foo1,将foo1传递到bar,以及从bar返回foo1

修改代码可以清楚地了解正在发生的事情:

#include <iostream>
struct Foo {
Foo()
: x(0)
{
std::cout << "Constructor called" << std::endl;
}
Foo(const Foo& foo)
: x(foo.x + 1)
{
std::cout << "Copy constructor called" << std::endl;
}
int x;
};
Foo bar(Foo foo)
{
std::cout << "B2:" << foo.x << std::endl;
foo.x++;
return foo;
}
int main()
{
Foo foo1;
Foo foo2 = foo1;
std::cout << "A:" << foo1.x << std::endl;
std::cout << "B:" << foo2.x << std::endl;
Foo foo3 = bar(foo1);
std::cout << "C:" << foo3.x << std::endl;
}

输出:

Constructor called
Copy constructor called
A:0
B:1
Copy constructor called
B2:1
Copy constructor called
C:3
  • 0 -> 1您将foo1复制到bar的参数。
  • 1 -> 2bar内递增x
  • 2 -> 3bar复制到临时返回值。

我数了三个增量。

执行时:

Foo foo2 = foo1;

您正在调用复制 CTR,因此 foo2.x 的值将为 1。 然后在调用时:

Foo foo3 = bar(foo1);

因为您不是通过引用传递的,所以 'bar' 的参数是使用复制 ctor (x == 1) 将 foo1 的副本创建到柱线中。之后,该副本的 x 成员递增 (x == 2) 并最终返回。当返回时不创建另一个副本,因为"返回值优化"(仍然 x == 2)。 最后,foo3 再次使用复制 ctor(x == 3) 进行初始化。

当你创建第一个foo1时,它的x为零。对bar的调用按值传递,因此它被复制 - 因此bar中的参数的值为 1。函数本身bar进一步递增x1,因此现在是 2。最后,return 语句再次按值返回,因此还有另一个副本 - 因此最终x为 3。

注意 RVO 在这里不适用,因为Foo不是按值返回局部变量 - 而是返回一个参数,该参数实际上必须复制。

从标准 [class.copy/31] 中,允许复制省略的情况,其中明确排除了返回函数参数的情况:

— 在具有类返回类型的函数中的 return 语句中,当 表达式是非易失性自动对象的名称(其他 比函数或 catch 子句参数)具有相同的 cv 不合格 类型作为函数返回类型,复制/移动操作可以是 通过将自动对象直接构造到 函数的返回值