Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/146.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 全局静态常量共享\u ptr被另一个共享\u ptr&\x27;为什么是毁灭者?_C++_C++11_Shared Ptr_Move Semantics - Fatal编程技术网

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()实际上是解决问题的全局变量

使用这些代码:

  • 在Visual Studio 2013中编译并运行而不进行调试,崩溃(Win8:程序停止工作)
  • 将main更改为test_2(),再次崩溃
  • 更改回test_1,如上所述设置3个断点并调试。它首先在#2处中断,然后在#1处中断,然后在#3处中断,然后弹出一个对话框说“已触发断点”,并在ntdll中中断,而“下一条语句”位于
    无断点处
    
  • 再次更改为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(标记范围的结束)