标量删除析构函数问题
scalar deleting destructor issue
我不明白为什么下面的代码会出错。
对象A的实例将被连续地推送到vector
(vectorA.push_back(A a)
)中。因此,有时vectorA
需要重新分配;将调用析构函数,也就是A
的析构函数被调用的地方,然后出现错误消息。
class A
{
long filePos;
union {
Recording* recording;
UINT64 timeStamp;
};
public:
inline A(long fpos, UINT64 ts) : filePos(fpos), timeStamp(ts) {}
~A()
{
if (getDetailedType() == RECORDING_TYPE)
if (recording)
delete recording; // error: scalar deleting destructor ???
}
inline short getDetailedType() const { return (short)(timeStamp % 5); }
A(const A& edi)
{
filePos = edi.filePos;
if (getDetailedType() == RECORDING_INFO)
recording = edi.recording;
else
timeStamp = edi.timeStamp;
}
}
class Recording : protected RECORDINGS
{
UINT64 timestamp;
float scalar;
public:
~Recording() // with or without this dtor, got same error
{
}
inline Recording()
{
timestamp = 0;
scalar = 2.0;
time = 0;
rate = 30;
type = 1;
side = 1;
}
}
typedef struct
{
UINT32 time;
float rate;
int type;
int side;
} RECORDINGS;
您的复制构造函数执行浅层复制。因此,现在有两个对象,它们都具有相同的recording
指针。
您应该进行深度复制,或者确保所有权正确转移(如果C++11
可用,则使用类似std::unique_ptr<Recording>
的东西。
请参阅这个关于深层副本和浅层副本之间区别的问题。
让我们看一些例子:
class ABadCopyingClass
{
public:
ABadCopyingClass()
{
a_ = new int(5);
}
~ABadCopyingClass()
{
delete a_;
}
private:
int* a_;
};
上面的类很糟糕,因为默认的复制构造函数和赋值运算符将执行浅层复制,并导致两个对象都认为自己拥有底层a_
对象。当其中一个超出范围时,a_
将被删除,而另一个将留下一个悬空指针,最终导致崩溃。
class ABetterCopyingClass
{
public:
ABetterCopyingClass()
a_(new int(5))
{
}
ABetterCopyingClass(const ABetterCopyingClass& r)
{
a_ = new int(*r.a_);
}
ABetterCopyingClass& operator=(const ABetterCopyingClass& r)
{
// in the case of reassignment...
delete a_;
a_ = new int(*r.a_);
return *this;
}
~ABetterCopyingClass()
{
delete a_;
}
private:
int* a_;
};
这个类稍微改善了我们的情况(注意,在这个简单的例子中忽略了正常的错误检查)。现在,复制构造函数和赋值运算符正确地执行必要的深度复制。这里的缺点是我们必须添加大量的样板代码——很容易出错。
class ACannonicalCopyingClass
{
public:
ACannonicalCopyingClass()
: a_(new int(5))
{
}
ACannonicalCopyingClass(ACannonicalCopyingClass&& moved_from)
{
a_ = std::move(moved_from.a_);
}
private:
std::unique_ptr<int> a_;
};
这个例子(仅限C++11)甚至更好。我们已经删除了大量的样板代码,但是这里的语义有点不同。在这种情况下,我们得到的不是深度复制,而是底层a_
对象的所有权转移。
最容易实现的版本(仅限C++11)是提供底层a_
对象共享所有权的版本。这是与您提供的示例最相似的版本,还有一个额外的好处,即它不会导致崩溃。
class ASharedCopyingClass
{
public:
ASharedCopyingClass()
: a_(std::make_shared<int>(5))
{
}
private:
std::shared_ptr<int> a_;
};
这个版本可以随意复制,底层的a_
对象将很乐意被引用计数。最后一个超出作用域的副本将引用计数设置为0
,这将触发内存释放。
我的心理调试技能告诉我,您忘记为A
实现一个副本构造函数,然后在副本被销毁时导致Recording
的双重删除。
矢量的增长将触发复制-销毁对。
- 类中C++析构函数的 Xcode 问题
- 为什么我以前调用析构函数的方式会导致模因问题
- 二叉搜索树析构函数问题
- 与C++析构函数相比,C#析构函数和GC并没有真正解决问题
- C++二进制树递归析构函数问题
- 我不明白析构函数有什么问题?
- 创建'new'实例可以解决析构函数崩溃问题?
- c++析构函数解分配问题
- 为什么我的析构函数导致我的链表出现问题
- 析构函数问题 + 列表显示
- 崩溃,可能是由于构造函数或析构函数中的某些问题
- 通用二进制树节点析构函数问题
- 析构函数的 AVL 树内存问题
- 标量删除析构函数问题
- 在我的程序中"无符号"之前的预期主表达式(析构函数和构造函数问题)
- 未调用析构函数,程序异常退出时出现问题
- C++和析构函数(嵌套类和一般问题)
- 提升::p ython 受保护的析构函数问题
- c++的析构函数有问题
- c++问题析构函数