繁体   English   中英

当我通过参数by-value时对象被破坏?

[英]When the object destructed while I pass the argument by-value?

给出以下代码:

#include <iostream>
using namespace std;
class A {
public:
    A() {
    }
    A(const A& a) {
        cout << "A copy ctor" << endl;
    }
    virtual ~A() {
        cout << "A dtor" << endl;
    }
    virtual void type() const {
        cout << "This is A" << endl;
    }
};
class B: public A {
public:
    virtual ~B() {
        cout << "B dtor" << endl;
    }
    virtual void type() const {
        cout << "This is B" << endl;
    }
};
A f(A a) {
    a.type();
    return a;
}
const A& g(const A& a) {
    a.type();
    return a;
}
int main() {
    A *pa = new B();
    cout << "applying function f:" << endl;
    f(*pa).type();
    cout << "~~~ delete: ~~~" << endl;
    delete pa;
    return 0;
}

我得到以下输出:

应用函数f:
副本ctor
这是一个
副本ctor
这是一个
一个dtor
一个dtor
~~~删除:~~~
B dtor
一个dtor

但我不明白。 它看到,虽然我们从存在f对象有没有破坏。 为什么它没有被破坏? (毕竟,我们超出了函数的范围,因此它必须被销毁,不是吗?)

注意:我强调了有问题的行(我不明白它为什么按此顺序发生)

我们转到函数f,此时,我们调用copy c'tor并打印“A copy ctor”(Ok),之后,我们返回函数f并转到type(),然后,它是打印“这是A”,现在我们从函数f中取出,所以我们调用copy c'tor,因此将打印“A copy ctor”,但是,现在,析构函数没有被调用(当我们从功能f)..?

我认为输出将如下(根据上面的描述):

应用函数f:
副本ctor
这是一个
副本ctor (逃避type
一个dtor (从type逃脱)
这是A (主要)
~~~删除:~~~
B dtor
一个dtor

C ++标准允许在函数范围内或在调用范围内销毁按值函数参数。

如果在调用范围内,它在完整表达式的末尾被销毁(通常是; )。 如果在函数内,则在构造返回值并销毁自动存储本地之后销毁它。

A *pa = new B();

创建B ,具有A子对象基础。

cout << "applying function f:" << endl;
f(*pa)//.type();

创建*pa切片副本作为f的参数。 输出是A copy ctor\\n

A f(A a) {
  a.type();
  return a;
}

A .type A的实例上调用。 请注意,此A*pa的副本,但它只是*paA部分的副本。

输出为This is A ,后跟A(A&&)移动ctor,后跟A dtor 在你的情况下,你有一个复制ctor而不是一个移动ctor,所以它被称为。 不能省略此复制/移动,因为您不能从函数参数中删除。 输出是A copy ctor

此时,编译器可以可选地将A f的参数的A存档。 你的编译器不破坏变元到f这里。

f(*pa).type();

f返回的临时A现在调用了.type() 这里没有多态性; 直接调用方法A::type() 输出是This is A

然后我们到达完整表达的末尾。

现在,通过返回的临时f被破坏,随后的参数f如果前面没有被破坏。 所以输出是A dtor

cout << "~~~ delete: ~~~" << endl;
delete pa;

B对象*pa被销毁,然后内存被回收。 由于~A是虚拟的,因此在*pa上调用正确的析构函数。

输出为B dtor\\nA dtor\\n

执行功能参数销毁时的行为是实现定义的:

[expr.call / 4

实现定义参数的生命周期是在定义它的函数返回时还是在封闭的完整表达式的末尾结束。

在您的具体情况下,实现选择后者。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM