【问题标题】:How is a local variable created in functions?如何在函数中创建局部变量?
【发布时间】:2018-02-12 20:36:29
【问题描述】:

假设我有这个代码:

#include <iostream>
using namespace std;

class A{
public:
    A() { cout << "In normal ctor\n"; }
    A(const A& a) { cout << "In cpy ctor\n";  }
    A(A&& a) { cout << "In move ctor\n"; }
    ~A() { cout << "In dtor\n"; }
};

A func(A a) {
    return a;
}

void main(){
    A a1;
    A a2 = func(a1);
}

输出如下:

In normal ctor
In cpy ctor
In move ctor
In dtor
In dtor
In dtor

现在我无法理解函数“func”内部发生的事情。

当 a1 被发送到函数时,函数不会通过 Ref 接收它,而是“创建”它自己的 a1 版本,即“a”。

这就是为什么当函数结束时,对象“死亡”并成为析构函数。

那么为什么不把它也交给构造器呢? (假设那里真的创建了一个本地对象)

是否有任何在幕后发生的复制?

提前致谢!

【问题讨论】:

  • “那么为什么不把它也交给构造函数”它确实In cpy ctor
  • but rather it "creates" it's own version,是的,它被称为复制构造,你在In cpy ctor中看到它。
  • @tkausl 但不是因为“A a2 = func(a1)”的副本吗?它不在函数内部
  • @Martin 不,这个作业被优化为移动构造,In move ctor
  • @freakish 哦,我明白了,所以复制构造函数是因为函数中的“创建”而发生的?此举实际上是主要的吗? (因为它是一个 RVALUE)

标签: c++ variables constructor scope compilation


【解决方案1】:

以下是发生的情况(您的程序的打印输出和解释):

  • 在正常 ctor 中 - 这发生在 A a1;main
  • 在 cpy ctor 中 - 当 A afunca1main 初始化时会发生这种情况
  • In move ctor - 当func 中的aa1 的副本)设置为a2 时会发生这种情况(请参阅copy elision 作为回报)
  • 在 dtor 中 - a1 的副本被销毁
  • 在 dtor 中 - a2 被销毁
  • 在 dtor 中 - a1 被销毁

我认为这里的关键是了解移动构造函数在创建a2 中的作用。您的func 按值返回A,应将其复制到a2。但是,C++ 编译器意识到您的程序在赋值后无法使用原始值,因此它通过调用移动构造函数来优化调用。

【讨论】:

  • 非常感谢!现在我看到了我遇到的错误,我认为复制构造函数发生在主函数中,而它实际上发生在函数中,所以它实际上确实创建了“a”!
【解决方案2】:
void main(){
    A a1; -- > Normal constructor
    A a2 = func(a1); --> Copy(a1 to a), Move(a to a2), destructor(a)
} -->  destructor a1, a2

这就是您按该顺序看到输出的原因。

【讨论】:

    【解决方案3】:

    func 通过副本传递了一个 A (即没有引用,它不是指针等)。这就是调用复制构造函数的原因。创建之后,它被移动到 a2 的位置,因此是移动构造函数。移动后,a 被销毁(因为 func 返回并且超出范围),然后 a1 和 a2 都被销毁(因为 main 返回)。

    你问为什么它没有进入构造函数,但它确实进入了。对于您创建的每个 A,都会调用一个不同的构造函数,首先是 a1(通常),然后是 a in func(通过复制),最后是 a2(通过移动)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-05
      • 1970-01-01
      相关资源
      最近更新 更多