【问题标题】:Object not deleted before new is assigned在分配新对象之前未删除对象
【发布时间】:2016-08-18 10:11:53
【问题描述】:

我有点困惑,因为我确信这应该会有所不同。看看这个代码示例:

#include <iostream>
#include <string>

using namespace std;

class base
{
    public:
    virtual ~base() = default;
};

class derived : public base
{
    private:
    int a = 0;
    int *b = nullptr;
    std::string lol;

    public:
    derived(std::string s) : b(new int(6)), lol{s} { cout << "ctor " << lol << endl; }
    derived(derived const& d) : lol{d.lol + " copy"} {cout << "copy " << lol << endl; }

    virtual ~derived() { cout << "dtor " << lol << endl; delete b; }

    virtual void superFunction() { cout << "OMG " << lol << endl; }
};

int main()
{
    derived a("a");
    derived b("b");
    a = b;
}

所有优化关闭的程序输出是:

ctor a
ctor b
dtor b
dtor b

我确信在这种情况下编译器应该生成删除对象a 并使用复制构造函数创建新对象的代码。相反,它使用隐式声明的operator=

有人能解释为什么吗?或者指出我的 C++ 标准。

谢谢。

【问题讨论】:

标签: c++ copy-constructor assignment-operator deep-copy


【解决方案1】:

当你写a = b;时,编译器会调用赋值运算符,如果代码中不存在并且没有标记为已删除,它将自动生成。仅当您尝试从另一个对象初始化一个新对象时才使用复制构造函数,如下所示:

derived a("a");
derived b = a;

此外,您的代码在 main 返回之前崩溃,因为它试图删除 b,它指向 aba = b; default-assignment 之后的同一内存。

如果你想在a = b; 执行后用derived 析构函数删除a,你只需要复制和交换习语。 What is the copy and swap idiom? 对如何在传统和现代 C++ 中做到这一点有一个很好的答案。从该答案中正确实施四规则将完全符合 DRY 原则并帮助您避免内存问题。请注意将参数传递给operator= 按值 的绝妙技巧,它使编译器选择适当的构造函数(复制或移动)并允许您只编写四个方法而不是所有five

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-04
    • 1970-01-01
    • 2023-03-14
    • 2018-10-01
    相关资源
    最近更新 更多