gpt4 book ai didi

c++ - std::vector push_back 和类构造函数没有被调用?

转载 作者:行者123 更新时间:2023-11-30 02:04:22 24 4
gpt4 key购买 nike

我有这样的课

class variable
{
public:
variable(int _type=0) : type(_type), value(NULL), on_pop(NULL)
{
}

virtual ~variable()
{
if (type)
{
std::cout << "Variable Deleted" <<std::endl;
on_pop(*this);
value=NULL;
}
}

int type;
void* value;
typedef void(*func1)(variable&);
func1 on_pop;
}

然后我像这样将实例推送到 std::vector 中:

stack.push_back(variable(0));

我希望 variable 的析构函数将被调用,但 if 在将值分配给 type 之前不会进入,因为我希望在将实例复制到 vector 时调用我提供的构造函数。但出于某种原因,事实并非如此。

在调用 stack.push_back 之后,析构函数(拷贝的?)运行并且类型具有一些随机值,就像从未调用过构造函数一样。

我似乎无法弄清楚我做错了什么。请帮忙! ^_^

编辑:

好的,这是一个独立的例子来说明我的意思:

#include <iostream>
#include <vector>

class variable
{
public:
variable(int _type=0) : type(_type), value(NULL), on_pop(NULL)
{
}

~variable()
{
if (type)
{
std::cout << "Variable Deleted" <<std::endl;
on_pop(*this);
value=NULL;
}
}

int type;
void* value;

typedef void(*func1)(variable&);
func1 on_pop;
};

static void pop_int(variable& var)
{
delete (int*)var.value;
}

static void push_int(variable& var)
{
var.type = 1;
var.value = new int;
var.on_pop = &pop_int;
}

typedef void(*func1)(variable&);
func1 push = &push_int;

int main()
{
std::vector<variable> stack;

stack.push_back(variable(0));
push(stack[stack.size()-1]);

stack.push_back(variable(0));
push(stack[stack.size()-1]);

stack.push_back(variable(0));
push(stack[stack.size()-1]);

return 0;
}

上面的程序输出如下:

Variable Deleted
Variable Deleted
Variable Deleted
Variable Deleted
Variable Deleted
Variable Deleted

Process returned 0 (0x0) execution time : 0.602 s
Press any key to continue.

最佳答案

欢迎来到 RVO 和 NRVO。这基本上意味着编译器可以跳过创建冗余的对象——即使它的构造函数和析构函数有副作用。您不能依赖立即复制或移动到实际存在的对象。

编辑:vector 中的实际值根本不能省略。只能省略中间变量variable(0)vector 中的对象仍必须像往常一样构造和销毁。这些规则仅适用于临时人员。

编辑:您为什么要编写自己的资源管理类?您可以简单地将 unique_ptr 与自定义删除器一起使用。还有你自己的 RTTI?

每个被破坏的对象必须已经被构造。标准中没有违反此规定的规则。 RVO 和 NRVO 只会在您开始时出现问题,例如,在构造函数/析构函数中修改全局变量。否则,它们对程序的正确性没有影响。这就是为什么它们是标准的。你肯定做错了什么。

最后,我只是不确定 WTF 到底发生在您身上,以及它为什么不起作用或“起作用”应该是什么。发布 SSCCE。

编辑:根据您的 SSCCE,绝对没有出现任何问题。这完全是预期的行为。您没有遵守三原则 - 也就是说,您在析构函数中销毁了资源,但没有努力确保您确实拥有有问题的资源。您的编译器生成的复制构造函数正在破坏您的逻辑。您必须阅读三法则、 copy-and-swap 以及 C++ 中用于资源处理的类似习语,并且最好使用已经作为标准提供的智能指针,如 unique_ptr,它没有这些问题。

毕竟,您创建了 variable 的六个实例 - 三个临时变量在堆栈上,三个在 vector 中。所有这些都调用了它们的析构函数。问题是您从未考虑过复制操作或复制会做什么或这些临时对象会发生什么(提示:它们会被破坏)。

考虑等价的例子

int main()
{
variable v(0);
push_int(v);
variable v2 = v;
return 0;
}

变量 v 被构造并分配一个新的 int 一切都很好。但是等等 - 然后我们将它复制到 v2。编译器生成的构造函数复制所有位。然后 v2v 都被销毁 - 但它们都指向相同的资源,因为它们都持有相同的指针。双重删除比比皆是。

您必须定义复制(共享所有权 - std::shared_ptr)或移动(唯一所有权 - std::unique_ptr)语义。

编辑:只是一个简短的说明。我观察到您实际上不会 push 到项目中,直到它们已经在 vector 中。但是,当您添加额外的元素时必须调整 vector 大小时,会出现相同的效果,而根本原因是相同的。

析构函数被调用了 6 次。 A 构造函数被调用了六次。只是不是您想要的那种。

关于c++ - std::vector push_back 和类构造函数没有被调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10764974/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com