我的课是这样的
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));我期望调用变量的析构函数,但if不会进入,直到为type赋值,因为我期望我提供的构造函数将在实例被复制到向量中时被调用。但出于某种原因,情况并非如此。
调用stack.push_back后,析构函数(副本的?)并且type有一些随机值,就像从未调用过构造函数一样。
我似乎想不出我做错了什么。请帮帮我!^_^
编辑:
好的,这里有一个自包含的例子来说明我的意思:
#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.发布于 2012-05-26 17:07:26
欢迎来到RVO和NRVO。这基本上意味着,如果对象是多余的,编译器可以跳过创建对象-即使它的构造函数和析构函数有副作用。您不能依赖于立即复制或移动到实际存在的对象。
编辑:vector中的实际值根本不能省略。只能省略中间变量variable(0)。vector中的对象仍然必须像往常一样构造和析构。这些规则仅适用于临时用户。
编辑:为什么要编写自己的资源管理类?您可以简单地使用带有自定义删除器的unique_ptr。你自己的RTTI呢?
每个被析构的对象都必须被构造。在标准中没有违反这一点的规则。RVO和NRVO只有在您开始时才会出现问题,例如,修改构造函数/析构函数中的全局变量。否则,它们对程序的正确性没有任何影响。这就是为什么他们是标准的。你一定是做错了什么。
归根结底,我只是不确定WTF到底发生在你身上,为什么它不工作,或者什么是“工作”。发布SSCCE。
编辑:根据你的SSCCE,绝对不会出任何问题。这完全是意料之中的行为。您没有遵守规则三-即,您销毁析构函数中的资源,但没有努力确保您实际拥有有问题的资源。编译器生成的复制构造函数正在破坏您的逻辑。您必须阅读有关C++中的三个规则、复制和交换以及类似的资源处理习惯用法,并且最好使用已经作为标准提供的智能指针,如unique_ptr,它没有这些问题。
毕竟,您创建了六个variable实例-三个在堆栈上,三个在向量内。所有这些都有自己的析构函数调用。问题是你从来没有考虑过复制操作,或者复制会做什么,或者这些临时文件会发生什么(提示:它们被销毁了)。
考虑同样的例子:
int main()
{
variable v(0);
push_int(v);
variable v2 = v;
return 0;
}变量v被构造并分配一个新的int,一切都很顺利。但是等等--然后我们把它复制到v2中。编译器生成的构造函数复制所有的位。然后v2和v都会被销毁-但它们都指向相同的资源,因为它们都持有相同的指针。双删除法比比皆是。
您必须定义copy (共享所有权- std::shared_ptr)或move (唯一所有权- std::unique_ptr)语义。
编辑:只是一个简单的注释。我观察到,实际上直到项目已经在向量中之后,才会push到项目中。但是,如果在添加其他元素时必须调整向量的大小,并且基本原因是相同的,则会出现相同的效果。
析构函数被调用了6次。一个构造函数会被调用六次。只是不是你想要的那个。
发布于 2012-05-26 21:00:40
好的。我已经阅读了更多关于不同容器的内部特性,显然,我在这里试图完成的工作是std::deque。
https://stackoverflow.com/questions/10764974
复制相似问题