1

为什么输出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
4

4 回答 4

1

我相信这里有三个复制构造函数在起作用, line foo2 = foo1foo1into的传递和frombar的返回。foo1bar

修改代码可以清楚地说明发生了什么:

#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
于 2016-06-14T15:16:21.657 回答
0

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

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

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

— in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value

于 2016-06-14T15:19:26.580 回答
0
  • 0 -> 1 You copy foo1 to the parameter of bar.
  • 1 -> 2 You increment x within bar.
  • 2 -> 3 You copy bar to the temporary return value.

I count three increments.

于 2016-06-14T15:23:10.803 回答
0

When doing:

Foo foo2 = foo1;

you are calling the copy ctor, so foo2.x's value will be 1. Then when calling:

Foo foo3 = bar(foo1);

because you are not passing by reference the argument of 'bar' is created a copy of foo1 into bar using the copy ctor (x == 1). After that that copy's x member is incremented(x == 2) and at last is returned. When returning is not created an other copy because 'return value optimization'(still x == 2). Finally foo3 is initialized using again the copy ctor(x == 3).

于 2016-06-14T15:30:33.260 回答