在循环内部创建的返回变量导致析构函数被调用两次

问题描述 投票:0回答:1

我试图理解C ++标准关于从函数返回对象时应如何/何时调用析构函数的说法-考虑这个简单的结构和两个功能-

#include <iostream>
int g = 0;
struct foo {
    int myid;
    foo() {
        myid = g;
        g++;
        std::cout << "Created " << myid << std::endl;
    }
    ~foo() {
        std::cout << "Destroyed " << myid << std::endl;
    }
};

foo bar(void) {
    int i = 0;
    for (foo s; i < 10; i++) {
        if (i == 5)
            return s;
    }
}
foo bar2(void) {
    int i = 0;
    foo s;
    for (; i < 10; i++) {
        if (i == 5)
            return s;
    }
}

int main() {
    bar();
    bar2();
    return 0;
}

我正在尝试跟踪析构函数的调用次数。上面程序的输出是-

Created 0
Destroyed 0
Destroyed 0
Created 1
Destroyed 1

我可以理解bar2的行为。对象创建一次并销毁(我相信析构函数是从main调用的)。但是在bar中,在循环内声明对象时。它将析构函数调用两次。这种差异的原因是什么?

是不是这种情况将这种行为留给实现(由于复制省略?),而g ++在这两种情况下都选择了这种行为?如果是这样,我该如何编写此函数,以便获得可预测的行为。我需要将析构函数的调用次数与构造函数的调用次数完全相同(最好以相反的顺序)。我同意,只要构造函数也被调用两次,析构函数就会被调用两次。原因是因为我在构造函数内部分配了一些数据,并在析构函数内部释放了数据。

c++ destructor copy-elision
1个回答
0
投票

添加此代码

foo(const foo& rhs) {
    myid = g;
    g++;
    std::cout << "Created from copy " << myid << std::endl;
}

这是一个复制构造函数,也只是在您不知道的情况下才被调用,因为您使用的是默认版本,该版本显然不打印任何内容,也不增加计数器。

© www.soinside.com 2019 - 2024. All rights reserved.