简体   繁体   English

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

[英]Destructor of struct called before assignment operator

I have a struct, Foo, with a pointer array of Bar. 我有一个结构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;
    }
};

I call it like this 我这样称呼它

Foo baz = fooFunc();

(It seems) that if I create an instance of Foo (f) inside a function (fooFunc) and return it, the destructor is called before the value is returned as I lose the contents of _BarList. (似乎)如果在函数(fooFunc)中创建Foo(f)的实例并返回它,则在返回值之前会调用析构函数,因为我丢失了_BarList的内容。

This makes sense as it was created within the function. 这是在函数内创建的,这很有意义。 Here is an example. 这是一个例子。

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

If I return an instance of Foo directly on the return, the destructor of that item isn't called until after the equals operator has been called (by the equals statement on the line of the call). 如果我直接在返回值上返回Foo的实例,则直到调用equals运算符之后(通过调用行上的equals语句),才调用该项目的析构函数。

Foo fooFunc()
{
    return Foo();
}

I suppose this makes sense as I am creating Foo inside the object, and things are cleared up before the object is returned. 我想这在我在对象内部创建Foo时是有道理的,并且在返回对象之前先清除所有内容。

I think I can resolve this by doing the return like this (after writing a new constructor to take Foo): 我想我可以通过这样的返回(在编写一个新的构造函数以接受Foo之后)来解决此问题:

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

1) Am I right in my assumptions? 1)我的假设正确吗?

2) Is there another way to do it that would not require so many repeated assignment operators being called? 2)是否有另一种方法可以执行,而无需调用那么多重复的赋值运算符?

Edit: Please consider that this function would normally do a lot more than just return Foo()! 编辑:请注意,此函数通常会执行很多操作,而不仅仅是返回Foo()!

Your class violates the Rule of three . 你的课违反了三规则 You have a destructor and a copy assignment operator, but no copy constructor. 您有一个析构函数和一个副本分配运算符,但是没有副本构造函数。 And the default one most definitely does not do what you need. 而且默认值绝对不能满足您的需求。

And note that all of these lines: 并注意所有这些行:

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

use the copy constructor, and not the assignment operator. 使用复制构造函数,而不是赋值运算符。 The assignment operator is only used for assigning to an existing object, never when creating/initialising a new one. 赋值运算符仅用于分配给现有对象,而在创建/初始化新对象时不使用。

I think the different behaviours you're experiencing are due to compiler optimization. 我认为您遇到的不同行为是由于编译器优化所致。

In any case, 任何状况之下,

Foo baz = fooFunc();

needs a copy constructor to work, because it will construct a new object from fooFunc's returned one. 需要一个复制构造函数来工作,因为它将根据fooFunc返回的对象构造一个新对象。

For instance 例如

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

This will guarantee fooFunc() return object is copied to the locally declared Foo baz object. 这将确保将fooFunc()返回对象复制到本地声明的Foo baz对象。

Note: Actually, calling operator= from copy constructor is a bad practice (but I mentioned it here to give you a quick answer and it will work in your case). 注意:实际上,从复制构造函数中调用operator=是一个不好的做法(但我在这里提到它是为了给您快速的答案,它会在您的情况下起作用)。 Check this post: Copy constructor and = operator overload in C++: is a common function possible? 检查一下这篇文章: 在C ++中复制构造函数和=运算符重载:是否可以使用通用函数?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM