gpt4 book ai didi

c++ - 标量删除析构函数问题

转载 作者:可可西里 更新时间:2023-11-01 18:06:03 26 4
gpt4 key购买 nike

我不明白为什么我会收到以下代码的错误。

对象 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。指针。

您应该进行深层复制,或者确保所有权已正确转移(如果 std::unique_ptr<Recording> 可用,请使用类似 C++11 的内容。

参见 This question on the difference between deep and shallow copies.

让我们看一些例子:

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 ,这将触发内存释放。

关于c++ - 标量删除析构函数问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17840579/

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