2

我已经设置了这个例子:

class UsefulClass {
public: 
        int id;
        const bool operator< (const UsefulClass &other) const {
                return this->id > other.id;
        }
        UsefulClass(int _id): id(_id) {
                std::cout << "constructing " << id << std::endl;
        }
        ~UsefulClass() {
                std::cout << "destructing " << id << std::endl;
        }
};
std::set<UsefulClass> set;
void create() {
        UsefulClass object_1(1);
        UsefulClass object_2(2);
        set.insert(object_1);
        set.insert(std::move(object_2));

        std::cout << "create end" << std::endl;
}
int main() {
        create();
        std::cout << "main end" << std::endl;
}

我期望对象set在程序结束时被删除时被破坏一次。但是对象被删除了两次:

constructing 1
constructing 2
create end
destructing 2
destructing 1
main end
destructing 1
destructing 2

为什么要set.insert在这里创建副本?

4

5 回答 5

4

中的对象与set本地的对象不同create()。中的那些set是使用复制构造函数和移动构造函数构造的,而不是构造函数UsefulClass(int),所以你看不到它们的构造。本地对象在函数create()返回时被销毁,然后set在全局清理main结束后销毁。

于 2013-06-12T12:38:00.540 回答
2

object_1 和 object_2 在堆栈上创建,一旦 create() 函数结束就会被销毁。它们需要被复制到由 set 的分配器管理的内存中。

如果您重新定义复制构造函数以跟踪其执行,您会注意到它在两个插入时都被调用。

于 2013-06-12T12:38:38.870 回答
1

3 规则适用于您的情况,如果您从 dtor 打印并想要有意义的跟踪,您也应该检测复制(并且可能移动)ctor。

如果你这样做,输出将是有意义的,并且应该正确配对。

于 2013-06-12T12:41:18.047 回答
0

因为您的对象在插入集合时会被复制。因此,当create()函数返回时,两个本地对象被销毁。结束后main,集合中的两个副本被销毁,导致第二对消息。

于 2013-06-12T12:35:44.840 回答
0

为了说明每个人在我之前所说的一切,只需创建这个简单的示例(它使用新的复制构造函数供集合使用,并使用全局变量在id每次执行构造函数时生成不同的 s ---它已经过测试,所以你可以把它放在一个文件中并编译):

#include <iostream>
#include <string>
#include <set>

using namespace std;

class UsefulClass {
    static int instance;
public:
    int id;
    int i;

    const bool operator<(const UsefulClass &other) const {
        return id < other.id;
    }

    UsefulClass(int i){
        id = instance++;
        this->i = i;
        cout    << "constructing "
            << id
            << ":"
            << this->i
            << endl;
    }

    UsefulClass(const UsefulClass& other) {
        id = instance++;
        i = other.i;
        cout    << "constructing "
            << id
            << ":"
            << i
            << endl;
    }

        ~UsefulClass(){
        cout    << "destructing "
            << id
            << ":"
            << i
            << endl;
    }
};

int UsefulClass::instance = 0;

std::set<UsefulClass> myset;

void create() {
        UsefulClass object_1(1);
        UsefulClass object_2(2);
        myset.insert(object_1);
    /* please, explain what you mean with std::move, or which move
     * have you used for the next statement.  All i have is
     * std::move(... ) for strings, but you have not defined
     * string UsefulClass::operator string();
     */
        myset.insert(/*std::move*/(object_2));

        cout    << "create end"
        << endl;
}

int main() {
        create();
        cout    << "main end"
        << std::endl;
}

因此,每当您创建 UsefulClass 对象时,您都会获得不同的实例 ID,并且您会看到在插入集合时它们被复制为新实例。您将看到每个对象的创建时间和删除时间。

$ pru
constructing 0:1
constructing 1:2
constructing 2:1
constructing 3:2
create end
destructing 1:2
destructing 0:1
main end
destructing 2:1
destructing 3:2
于 2014-08-22T08:07:21.380 回答