在分配新内容之前未删除对象

Din*_*ino 1 c++ deep-copy copy-constructor assignment-operator

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

#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;
}
Run Code Online (Sandbox Code Playgroud)

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

ctor a
ctor b
dtor b
dtor b
Run Code Online (Sandbox Code Playgroud)

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

有人可以解释原因吗?或者指向C++标准.

谢谢.

Ser*_*gey 5

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

derived a("a");
derived b = a;
Run Code Online (Sandbox Code Playgroud)

此外,您的代码在主要返回之前在尝试删除时崩溃,在默认分配之后b指向相同的内存.aba = b;

如果你想在执行后aderived析构函数删除a = b;,你只需要复制和交换习语.什么是复制和交换习惯用法?如何在遗留和现代C++中做到这一点有一个很好的答案.从该答案中正确实施四法则将完全符合DRY原则,并帮助您避免内存问题.注意通过参数传递operator= 的神话般的技巧,这使得编译器选择适当的构造函数(复制或移动)并允许您只编写四种方法而不是全部五种方法.