我正在尝试通过将delete运算符作为朋友函数重载来实现此目的。代码如下:
#include <iostream>
class HeapOnly
{
int x;
int y;
~HeapOnly()
{
}
public:
void friend operator delete(void* a);
};
void operator delete(void* p)
{
delete p;
}
int main()
{
HeapOnly *abc = new HeapOnly();
delete abc;
}
以上代码在Visual Studio中显示错误“错误C2248'HeapOnly ::〜HeapOnly':无法访问在类'HeapOnly中声明的私有成员”
我不明白为什么它会出错,因为删除操作符作为朋友函数被重载,因此它应该能够访问私有的析构函数。
答案 0 :(得分:2)
为什么尝试失败,请参见其他答案。我不知道是否可以以及是否可以实现只能在堆上实例化的类的一般目标,并且这是否可取,但是我对此表示怀疑。
但是,您可以做的是限制取消分配通过std::allocator
或std::default_delete
进行,这样就不可能使用简单的自动变量:
#include <iostream>
#include <memory>
#include <vector>
#include <algorithm>
class HeapOnly
{
~HeapOnly();
public:
bool operator < (HeapOnly const&) const;
friend class std::allocator<HeapOnly>;
friend class std::default_delete<HeapOnly>;
};
int main()
{
std::vector<HeapOnly> X(10); // okay
HeapOnly Y; // ERROR: cannot be destructed
std::sort(X.begin(),X.end()); // ERROR: requires automatic variables
std::vector<std::unique_ptr<HeapOnly>> Z(10); // okay
for(auto&z:Z)
z.reset(new HeapOnly);
std::sort(Z.begin(),Z.end(),[](std::unique_ptr<HeapOnly> const&x,
std::unique_ptr<HeapOnly> const&y)
{ return *x < *y; });
}
但是请注意,很多事情都依赖于自动变量,包括std::swap
和std::sort
(直接与std::sort
交往无济于事,因为它将工作委托给特定于实现的助手例程)。但是,您可以启用unique_ptr
(和shared_ptr
),这似乎与仅使用堆的类很自然,然后对指向的对象进行排序。
进一步注意,即使上面的代码可能适用于大多数(即使不是全部)STL实现,但不能保证。 std::allocator<>::destroy()
例如可以将销毁委托给助手函数,该助手函数是实现细节,因此不能成为朋友。
但是,您可以对此进行测试,并使用SFINAE规避此类情况。
答案 1 :(得分:1)
实际上并没有让您重载的“删除运算符”。有:
src
中所示;和delete abc
。换句话说,您从未重载不存在的“删除运算符”或将其声明为朋友。重载并声明为朋友的唯一东西是 deallocation函数。
删除表达式分两步进行操作:
因此,私有析构函数仍被视为不是该类的朋友的operator delete
直接调用。
我们可以做一些实验来验证:
代码1:不带main
声明:https://godbolt.org/g/WVmzNP
friend
代码2:将class HeapOnly
{
int x;
int y;
~HeapOnly() = default;
};
int main()
{
HeapOnly *abc = new HeapOnly();
delete abc;
}
声明为朋友:https://godbolt.org/g/9PVZ4C
main