我无法弄清楚为什么我会得到以下代码的错误.
对象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;
Run Code Online (Sandbox Code Playgroud)
Cha*_*had 15
您的复制构造函数执行浅复制.所以,现在你有两个具有相同recording指针的对象.
您应该进行深层复制,或者确保所有权得到正确转移(通过使用std::unique_ptr<Recording>if if C++11available等内容).
请参阅有关深拷贝和浅拷贝之间差异的此问题.
我们来看一些例子:
class ABadCopyingClass
{
public:
ABadCopyingClass()
{
a_ = new int(5);
}
~ABadCopyingClass()
{
delete a_;
}
private:
int* a_;
};
Run Code Online (Sandbox Code Playgroud)
上面的类很糟糕,因为默认的复制构造函数和赋值运算符将执行浅复制,并导致两个对象都认为它们拥有底层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_;
};
Run Code Online (Sandbox Code Playgroud)
这个类稍微改善了我们的情况(注意,在这个简单的例子中省略了正常的错误检查).现在,复制构造函数和赋值运算符正确执行必要的深度复制.这里的缺点是我们必须添加的样板代码量 - 很容易出错.
class ACannonicalCopyingClass
{
public:
ACannonicalCopyingClass()
: a_(new int(5))
{
}
ACannonicalCopyingClass(ACannonicalCopyingClass&& moved_from)
{
a_ = std::move(moved_from.a_);
}
private:
std::unique_ptr<int> a_;
};
Run Code Online (Sandbox Code Playgroud)
这个例子(仅限C++ 11)更好.我们删除了大量的样板代码,但这里的语义有点不同.在这种情况下,我们不是进行深度复制,而是转移底层a_对象的所有权.
要实现的最简单版本(仅限C++ 11)是提供底层a_对象的共享所有权的版本.这是与您提供的示例最相似的版本,还有额外的奖励,它不会导致崩溃.
class ASharedCopyingClass
{
public:
ASharedCopyingClass()
: a_(std::make_shared<int>(5))
{
}
private:
std::shared_ptr<int> a_;
};
Run Code Online (Sandbox Code Playgroud)
可以随意复制此版本,并且基础a_对象将很乐意被引用计数.超出范围的最后一个副本将引用计数设置为0,这将触发内存释放.
我的通灵调试技巧告诉我你忘了实现一个复制构造函数A,然后在Recording复制被销毁时导致双重删除.
向量的增长将触发复制 - 破坏对.
| 归档时间: |
|
| 查看次数: |
24331 次 |
| 最近记录: |