alt*_*gel 7 c++ shared-ptr c++11
我正在实现一个A我想要通过它专门管理的多态类型(称之为)std::shared_ptr.要允许shared_from_this在派生类的构造函数中A使用new,请使用然后将成员初始化std::shared_ptr为自身以自动管理其生命周期.为了帮助实现这一点,我决定使特定于类的operator new私有,并计划使用create()辅助函数而不是new和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();
}
Run Code Online (Sandbox Code Playgroud)
这编译并正常工作.当我将以下代码添加到正文时出现问题A:
struct A {
...
private:
void* operator new(size_t size){
return ::operator new(size);
}
void operator delete(void* ptr){
::operator delete(ptr);
}
...
};
Run Code Online (Sandbox Code Playgroud)
现在,这无法在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
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?为什么std::shared_ptr构造函数只是nullptr突然尝试接受?
编辑:是的,在实际的代码中,类确实派生自std::enable_shared_from_this,但没有必要重现错误.
Sto*_*ica 12
当我尝试你的代码时,我得到了一个完全不同的错误:
error C2248: 'A::operator delete': cannot access private member declared in class 'A'
Run Code Online (Sandbox Code Playgroud)
罪魁祸首就是这个
m_sharedthis(this)
Run Code Online (Sandbox Code Playgroud)
您提供指针,但没有删除器.因此,std::shared_ptr将尝试使用默认删除器,它可能包含delete您的类型上的表达式.由于删除器与您的类无关,因此无法访问私有operator delete.
解决方法是提供自定义删除器
m_sharedthis(this, [](A* a) {delete a;})
Run Code Online (Sandbox Code Playgroud)
已经在类的范围内定义的lambda可以operator delete在其定义的时候访问.
在一个无关的说明.您编写的代码将泄露所有这些对象.由于这些对象都有自己的强引用,它们如何达到零引用计数?考虑std:enable_shared_from_this改用.
隐藏的visual studio错误是由shared_ptr构造函数引起的,该构造函数仅针对不可删除的类型禁用指针:
template<class _Ux,
enable_if_t<conjunction_v<conditional_t<is_array_v<_Ty>, _Can_array_delete<_Ux>, _Can_scalar_delete<_Ux>>,
_SP_convertible<_Ux, _Ty>>, int> = 0>
explicit shared_ptr(_Ux * _Px)
Run Code Online (Sandbox Code Playgroud)
构造函数被禁用为c ++ 17状态:
如果删除表达式格式不正确,则此构造函数不参与重载解析.
这使得各种复制和移动构造函数成为唯一的单个参数构造函数,编译器选择移动构造函数作为最接近的匹配但不能将原始指针转换为shared_ptr<T>&&,nullptr_t错误消息的一部分是因为编译器正在尝试使用它作为可转换为的中间步骤shared_ptr<T>&&.
您需要提供自定义删除程序来解决此问题:
m_sharedthis(this, [](A* a) {delete a;})
Run Code Online (Sandbox Code Playgroud)
正如其他人所指出的,您的对象永远不会被删除,因为它们包含对自己的强烈引用.您应该更改m_sharedthis为a std::weak_ptr或使用std::shared_from_this.
| 归档时间: |
|
| 查看次数: |
659 次 |
| 最近记录: |