在赋值运算符之前调用的struct的析构函数

时间:2014-10-02 08:18:11

标签: c++ operator-overloading assignment-operator

我有一个结构,Foo,指针数组为Bar。

struct Foo
{
    Bar* _BarList;

    Foo()
    {
        _BarList = new Bar[1];
        _BarList[0] = Bar(10, 20);
    }

    Foo& operator=(const Foo& foo)
    {
        Bar* tmpBarList = new Bar[1];

        tmpBarList[0] = foo._BarList[0];

        delete[] _BarList;

        _BarList = tmpBarList;

        return *this;
    }

    ~Foo()
    {
        delete[] _BarList;
    }
};

我称之为

Foo baz = fooFunc();

(似乎)如果我在函数(fooFunc)中创建一个Foo(f)实例并返回它,则在返回值之前调用析构函数,因为我丢失了_BarList的内容。

这在函数中创建是有意义的。这是一个例子。

Foo fooFunc()
{
    Foo f = Foo();
    return f;
}

如果我在返回时直接返回Foo的实例,则在调用equals运算符之后才会调用该项的析构函数(通过调用行上的equals语句)。

Foo fooFunc()
{
    return Foo();
}

我认为这是有道理的,因为我在对象中创建了Foo,并且在返回对象之前清除了一些东西。

我想我可以通过这样做返回来解决这个问题(在编写一个新的构造函数来获取Foo之后):

Foo fooFunc()
{
    Foo f = Foo();
    return Foo(f);
}

1)我的假设是对的吗?

2)还有另一种方法可以不需要这么多的重复赋值运算符吗?

编辑:请注意,此功能通常不仅仅会返回Foo()!

2 个答案:

答案 0 :(得分:5)

您的课程违反了Rule of three。您有一个析构函数和一个复制赋值运算符,但没有复制构造函数。默认情况下,可以做你需要的。

并注意所有这些行:

Foo f = Foo();
return Foo(f);
Foo baz = fooFunc();

使用复制构造函数,而不是赋值运算符。赋值运算符仅用于分配现有对象,永远不会在创建/初始化新对象时使用。

答案 1 :(得分:3)

我认为您遇到的不同行为是由编译器优化造成的。

无论如何,

Foo baz = fooFunc();

需要一个拷贝构造函数来工作,因为它将从fooFunc返回一个构造一个新对象。

例如

Foo(const Foo& foo) : _BarList( NULL )
{
    ::operator=( foo );
}

这将保证将fooFunc()返回对象复制到本地声明的Foo baz对象。

注意:实际上,从复制构造函数调用operator=是一种不好的做法(但我在这里提到它可以给你一个快速的答案,它会适用于你的情况)。查看此帖子:Copy constructor and = operator overload in C++: is a common function possible?