【问题标题】:Double destructor call in C++C ++中的双重析构函数调用
【发布时间】:2021-03-17 14:56:19
【问题描述】:

我正在尝试使用流畅的界面创建对象配置器。 代码:

class Configurator {
public:
    Configurator() {
        printf("Constructor.\n");
    }

    ~Configurator() {
        printf("Destructor.\n");
        printf("String: %s\n", this->str_.c_str());
    }

    Configurator& Append(const std::string& str) {
        this->str_ += str;
        return *this;
    }

private:
    std::string str_;
};

Configurator PrepareConfigurator() {
    return Configurator();
}

Configurator PrepareWithSomeAppend() {
    return PrepareConfigurator().Append("hello").Append(", ");
}

int main() {
    printf("Start.\n");
    
    PrepareWithSomeAppend().Append("world!");
    
    printf("End.\n");
    return 0;
}

Class Configurator 仅在析构函数中打印字符串(我想这样做是为了不强制调用辅助方法来调用操作)。 Append 方法将字符串附加到私有字段字符串。 方法PrepareConfigurator 创建Configurator。 方法PrepareWithSomeAppend 调用PrepareConfigurator 并调用Append 方法并从函数返回对象。 在main 中,我再次调用Append 方法,我希望得到这样的输出:

Start.
Constructor.
Destructor.
String: hello, world!
End.

但我得到了输出:

Start.
Constructor.
Destructor.
String: hello, 
Destructor.
String: hello, world!
End.

为什么析构函数调用了两次?我该如何预防? 提前致谢!

编辑

我也尝试在PrepareWithSomeAppend 中创建Configurator,但问题没有解决。析构函数调用了两次。

Configurator PrepareWithSomeAppend() {
    return Configurator().Append("hello").Append(", ");
}

另外,我尝试从PrepareWithSomeAppend 返回对Configurator 的引用:

Configurator& PrepareWithSomeAppend() {
    return Configurator().Append("hello").Append(", ");
}

而且它也不起作用,析构函数在 PrepareWithSomeAppend 方法中调用本地对象,我在 main 函数中遇到分段错误错误,因为引用指向被破坏的对象。 如何防止在 PrepareWithSomeAppend 函数中调用本地对象的析构函数?还是不复制就返回一个对象?

【问题讨论】:

  • 您的对象被复制或移动(编译器为您生成复制和/或移动构造函数 - 抱歉没有阅读详细信息以检查哪个)。
  • 不用担心,您看不到另一个构造函数调用,因为它使用的是复制构造函数(隐式生成)。
  • 在你的输出语句中打印出this 的值,它会给你一个关于发生了什么的线索。你会看到this 是不同的。
  • @MarkRansom 规则三,遵循或,不会改变这里的行为。这里的问题是为什么 RVO 不会在这里发生

标签: c++ oop destructor fluent-interface


【解决方案1】:

在我看来,原因似乎是 PrepareConfigurator() 方法,因为它创建了一个新的 Configurator 对象。但是,我们也返回一个配置器结果。这意味着构造的对象在返回时被复制,我们一离开 PrepareConfigurator() 方法就销毁本地构造的对象。

尝试更改方法,使其返回引用或指针。

【讨论】:

    猜你喜欢
    • 2013-01-22
    • 2016-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-19
    • 2014-05-03
    • 2016-10-28
    • 2017-04-28
    相关资源
    最近更新 更多