【问题标题】:Why does a constructor when explicitly called return a temporary object, when it has no return type?为什么构造函数在显式调用时返回一个临时对象,而它没有返回类型?
【发布时间】:2020-11-03 08:48:54
【问题描述】:

我正在学习 C++ 中的 OOP,并且了解到我们可以显式调用构造函数,如下所示:

var obj = var(); // Assume var is a class and obj is an instance of an object of the class var.

据我所知,var()构造函数实例化一个临时对象,初始化它,然后发送它,以便对象obj复制它的内容.

现在我有两个疑问:

  1. 这种理解是否正确(即它是否以我认为的方式发生)?
  2. 我还了解到构造函数不会实例化对象,而是仅初始化对象。如果这是真的,那么为什么会在上述代码行的 RHS 上形成一个对象?如果 RHS 上没有对象形式,谁的内容将被复制到对象 obj?

【问题讨论】:

  • 构造函数不返回临时对象。它用于初始化对象的状态。在var obj = var() 中,var() 使用默认构造函数构造一个对象。该对象不是由构造函数返回。
  • 创建对象不是构造函数的责任,只是初始化它。简而言之,构造函数总是在已经创建的对象上被调用。
  • 你不能显式调用构造函数——它们没有名字也不能被引用。只是对象创建语法看起来和构造函数原型语法一模一样。

标签: c++ oop constructor


【解决方案1】:

创建对象的语法看起来像调用函数的语法,但它们是不同的。你不能调用构造函数。

在 C++17 中甚至没有两个对象。临时值var() 被具体化为obj。

【讨论】:

  • 是的,似乎确实如此。我已经放置了一个复制构造函数来查看是否正在发生“复制”并且它没有被调用 - 基本上暗示了你所说的。
【解决方案2】:

看看下面的反汇编代码:

https://godbolt.org/z/aP9eG3

class Hello {
public:
    Hello(int x) {this->x = x;}
int x;
};

int main() {
    Hello x = Hello(1);
    Hello y(2);

    x = y;
    return x.x;
}

Hello x = Hello(1); 行被翻译成这样:

    lea     rax, [rbp-4]
    mov     esi, 1
    mov     rdi, rax
    call    Hello::Hello(int)

逐行解释:

第 1 行。在堆栈上分配 4 个字节

第 2 行:移动 1 成为第一个函数调用参数

第 3 行:将新对象的地址作为参数传递

第 4 行,调用函数 Hello::Hello(int)

就是这样,没有副本。分配内存,就地构造对象。

Hello y(2); 行翻译成同样的东西。

最后,x = y; 行转换为:

    mov     eax, DWORD PTR [rbp-8]
    mov     DWORD PTR [rbp-4], eax
    mov     eax, DWORD PTR [rbp-4]

这是实际的内存副本。我认为这个例子说明了 C++ 的实际工作方式,比任何理论解释都要好。

【讨论】:

    【解决方案3】:

    事实上,通过创建你的类var的实例,对象是通过调用构造函数来创建的。所以如果你写var obj;,就会调用创建者。

    创建对象时已经调用了表达式var()。但由于没有指定,所以没有必要指定。指定你想要使用的构造函数类型更有趣,例如:

    var obj = var(foo);
    

    或

    var obj(foo);
    

    【讨论】:

    • 不确定你的意思。通过var obj = var();指定调用哪个构造函数是完全有效的。
    • 它是有效的,但已经被调用了...如果构造函数只为“特殊”构造函数指定,则更容易阅读,例如,如果你有几个像 var() 这样的构造函数
    • 这不是你的答案... 表达式 var() 在这里不正确;计算机正在搜索一个名为 var() 的函数,但没有任何线索可以理解它在类 var 中。
    猜你喜欢
    • 1970-01-01
    • 2016-10-10
    • 2011-10-10
    • 2015-12-14
    • 1970-01-01
    • 2014-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多