【问题标题】:Why destructor is not called? [duplicate]为什么不调用析构函数? [复制]
【发布时间】:2021-06-21 23:28:27
【问题描述】:

我写了两个程序来理解复制对象的概念。 第一个:

#include<bits/stdc++.h>
using namespace std;

class myInt
{
    int x;
public:
    myInt()
    {
        cout<< "default constructor is called" << endl;
    }
    myInt(int x)
    {
        cout<< "constructor is called with initializer" << endl;
        this->x = x;
    }
    ~myInt()
    {
        cout<< "destructor is called" << endl;
    }
};

myInt func(myInt ob)
{
    return ob;
}

int main()
{
    myInt ob1(2);
    func(ob1);
}

输出:

constructor is called with initializer
destructor is called
destructor is called
destructor is called

这里析构函数被调用了 3 次,这意味着创建了 3 个对象。一个用于对象“ob1”,一个用于 func() 内部的“ob”,另一个用于从 func() 返回“ob”。 我的第二个代码:

#include<bits/stdc++.h>
using namespace std;

class myInt
{
    int x;
public:
    myInt()
    {
        cout<< "default constructor is called" << endl;
    }
    myInt(int x)
    {
        cout<< "constructor is called with initializer" << endl;
        this->x = x;
    }
    ~myInt()
    {
        cout<< "destructor is called" << endl;
    }
};

myInt func(myInt ob)
{
    return ob;
}

int main()
{
    myInt ob1(2);
    myInt ob2 = func(ob1);
}

输出:

constructor is called with initializer
destructor is called
destructor is called
destructor is called

这里还创建了 3 个对象作为第一个对象。但是,当我将来自 func() 的返回对象存储在其中时,不应该再调用一个 'ob2' 的析构函数吗?为什么两种情况下析构函数调用的次数相同?

【问题讨论】:

  • 返回值优化:ob2 并没有真正创建。另请参阅:copy elision.
  • 看看这个question

标签: c++ class object destructor


【解决方案1】:

正如 cmets 中所指出的,由于复制省略,创建临时对象仅用于初始化另一个对象时可能会被省略。使用-fno-elide-constructors 编译您的代码以将其关闭,您将阅读 destructor is called 四次。这是demo

但是,在 c++17 中,情况有所不同。它保证在某些情况下省略副本(prvalue 用作具有相同类型的对象的初始化程序)。在那里,它不再被视为优化(即-fno-elide-constructors 在这里没有效果)。有关详细信息,请参阅这个漂亮的 articleproposal。以下example(从链接文章中窃取)可以在 c++17 中正常编译,因为我们保证不会调用复制/移动构造函数:

struct Foo {
  Foo() { std::cout << "Constructed" << std::endl; }
  Foo(const Foo &) = delete;
  Foo(const Foo &&) = delete;
  ~Foo() { std::cout << "Destructed" << std::endl; }
};

Foo f() {
  return Foo();
}

int main() {
  Foo foo = f();
}

【讨论】:

  • @Bob__ 我将它包含在我的答案中。感谢您指出这一点。
猜你喜欢
  • 2021-03-20
  • 2015-04-28
  • 2015-08-21
  • 2021-02-18
  • 2014-01-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多