c++ - 为什么让 operator new 私有中断 std::shared_ptr?
问题描述
我正在实现一个多态类型(称为它A
),我想通过std::shared_ptr
. 为了允许shared_from_this
在派生类的构造函数中使用,A
分配使用new
,然后将成员初始化std::shared_ptr
为自身以自动管理其生命周期。为了帮助实现这一点,我决定将特定类设为operator new
私有,并计划使用create()
辅助函数而不是new
and make_shared
。该设计可能看起来有点滑稽,但在我正在开发的 UI 库的上下文中是有意义的。一个最小的可重现示例如下:
struct A {
A() : m_sharedthis(this) {
}
void destroy(){
m_sharedthis = nullptr;
}
std::shared_ptr<A> self() const {
return m_sharedthis;
}
private:
friend std::shared_ptr<A> create();
std::shared_ptr<A> m_sharedthis;
};
std::shared_ptr<A> create(){
auto a = new A();
return a->self();
}
这可以编译并正常工作。当我将以下代码添加到的主体时出现问题A
:
struct A {
...
private:
void* operator new(size_t size){
return ::operator new(size);
}
void operator delete(void* ptr){
::operator delete(ptr);
}
...
};
现在这无法在 MSVC 2017 上编译,并带有相当神秘的错误消息:
error C2664: 'std::shared_ptr<A>::shared_ptr(std::shared_ptr<A> &&) noexcept': cannot convert argument 1 from 'A *' to 'std::nullptr_t'
note: nullptr can only be converted to pointer or handle types
这里发生了什么?为什么构造函数只是突然std::shared_ptr
尝试接受?nullptr
编辑:是的,在实际代码中,该类确实派生自std::enable_shared_from_this
,但没有必要重现该错误。
解决方案
当我尝试你的代码时,我得到了一个完全不同的错误:
error C2248: 'A::operator delete': cannot access private member declared in class 'A'
罪魁祸首是这个
m_sharedthis(this)
您提供了一个指针,但没有删除器。因此std::shared_ptr
将尝试使用默认删除器,它可能包含delete
您的类型的表达式。由于该删除器与您的课程无关,因此它无法访问 private operator delete
。
一种解决方法是提供自定义删除器
m_sharedthis(this, [](A* a) {delete a;})
已在类范围内定义的 lambda 可以operator delete
在其定义点访问。
在一个无关的笔记上。您编写的代码将泄漏所有这些对象。既然对象都持有对自己的强引用,那么它们怎么会达到零引用计数呢?考虑std:enable_shared_from_this
改用。
推荐阅读
- python - 如何修复windows10中python中的多处理问题
- java - 从 gmail 收件箱中检索特定主题的邮件
- excel - VBA:使用“查找”获取值的行/修复对象变量错误
- sql - 显示超过 3 个工作日的工作
- c# - 我无法在 C# 中为我的 Unity 游戏编写赢得关卡的脚本。我需要帮助
- javascript - 从 morris.js 折线图中删除中间多余的 x 轴线
- jquery - 如何更改字体真棒图标和按钮类 onclick?
- sql - SQL teradata - 正则表达式数字
- ubuntu - Ubuntu crontab 没有一直运行
- spring - 意外的 Vaadin 会话过期和并行的 spring boot 应用程序