C++ 全局静态常量共享\u ptr被另一个共享\u ptr&\x27;为什么是毁灭者?
我正在编写一个文件管理器,当我打开一个文件夹两次时,看到了可复制的崩溃。 要缩小相关代码,请执行以下操作:C++ 全局静态常量共享\u ptr被另一个共享\u ptr&\x27;为什么是毁灭者?,c++,c++11,shared-ptr,move-semantics,C++,C++11,Shared Ptr,Move Semantics,我正在编写一个文件管理器,当我打开一个文件夹两次时,看到了可复制的崩溃。 要缩小相关代码,请执行以下操作: #包括 #包括 #包括 名称空间myns{ 使用std::shared_ptr; } 阶级基础{ 公众: 虚拟~Base(){} }; 类派生的\u 1:公共基{ 公众: ~Derived_1(){}//断点1 }; myns::共享的\u ptr派生的\u 1\u ptr(){ 静态常量myns::shared_ptr r{new-Derived_1}; 返回r; } 类派生的_2:公共
#包括
#包括
#包括
名称空间myns{
使用std::shared_ptr;
}
阶级基础{
公众:
虚拟~Base(){}
};
类派生的\u 1:公共基{
公众:
~Derived_1(){}//断点1
};
myns::共享的\u ptr派生的\u 1\u ptr(){
静态常量myns::shared_ptr r{new-Derived_1};
返回r;
}
类派生的_2:公共基{};
myns::共享_ptr派生的_2_ptr(){
静态常量myns::shared_ptr r{新派生的_2};
返回r;
}
std::vector all_派生的_ptrs(){
返回{Derived_1_ptr(),Derived_2_ptr()};//无断点
}
无效测试_1(){
所有_派生的_ptrs();//断点2
所有_派生的_ptrs();//断点3
}
无效测试_2(){
{
std::向量t{Derived_1_ptr(),Derived_2_ptr()};
}
{
std::向量t{Derived_1_ptr(),Derived_2_ptr()};
}
}
int main(){
测试_1();
返回0;
}
派生的_1_ptr()和派生的_2_ptr()实际上是解决问题的全局变量
使用这些代码:
无断点处李>
再次更改为test_2,在构建第一个t
之后设置断点,并在调试窗口中查看t
t[0]
有1个强引用,而t[1]
有2个强引用
因此,我可以推断,当构造第一个向量时,Derived_2_ptr()
被正确复制(++reference_count),而Derived_1_ptr()
似乎是从静态常量r中窃取(移动?)(reference_count仍然是1)。当第一个向量被销毁时,Derived_2_ptr()
正确执行--reference_count并仍处于活动状态,但是Derived_1_ptr()
在创建第二个向量(它是全局静态变量!)之前丢失其唯一引用并消亡
为什么?移动构造函数可以应用于静态常量
事物吗?
我尝试将Derived_x_ptr()
的返回类型更改为const myns::shared_ptr&
或myns::shared_ptr
,两者都正常工作
另外,如果我删除派生的_2_ptr()并使所有的_派生的_ptr返回{Derived_1_ptr(),nullptr}
,派生的_1_ptr()会神奇地工作
如果我改用boost::shared_ptr,问题就隐藏了(没有程序停止对话框),但是~Derived_1()调用得太早了
这是怎么回事?标准允许这种移动吗?它是微软特有的东西,还是VS2013特有的东西(我没有其他的C++11编译器)?有什么想法吗?我想你可能看到了这个bug:。或者这个(可能是同一个):我想你可能看到了这个bug:。或者这个(可能是同一个):我看到对std::initializer\u list构造函数的调用不好,begin参数很好,但end参数未初始化。@HansPassant:你是说std::initializer\u list::initializer\u list(const\u Elem*\u First\u arg,const\u Elem*\u Last\u arg)?是的,如果我在这里断点_Last_arg未初始化,但我认为这并不重要,因为[_First_arg,_Last_arg)是一个范围:_First_arg是派生的_1,_First_arg+1是派生的_2,_First_arg+2==_Last_arg(标记范围的结束)我看到对std::initializer\u list构造函数的调用不好,begin参数是好的,但是end参数是未初始化的。@HansPassant:你是说std::initializer\u list::initializer\u list(const\u Elem*\u First\u arg,const\u Elem*\u Last\u arg)?如果我在这里的断点\u Last\u arg是未初始化的,但我认为这没关系,因为[_First_arg,_Last_arg)是一个范围:_First_arg是派生的_1,_First_arg+1是派生的_2,_First_arg+2==_Last_arg(标记范围的结束)