【问题标题】:Downcasting a shared_ptr to a derived class containing a weak_ptr c++11将shared_ptr向下转换为包含weak_ptr c++11的派生类
【发布时间】:2017-05-01 09:33:49
【问题描述】:

尝试使用std::static_pointer_cast 向下转换std::shared_ptr 时发生段错误,其中派生类也包含std::weak_ptr

这是一个 MWE:

#include<iostream>                                                                                                                                                                                                  
#include<memory>                                                                                                                                                                                                    

struct Base {};                                                                                                                                                                                                     

struct Derived : Base                                                                                                                                                                                               
{                                                                                                                                                                                                                   
    std::weak_ptr<int> wp;                                                                                                                                                                                          
};                                                                                                                                                                                                                  

int main()                                                                                                                                                                                                          
{                                                                                                                                                                                                                   
    auto pB = std::make_shared<Base>();              // Create a pointer to Base class instance                                                                                                                     
    auto pD = std::static_pointer_cast<Derived>(pB); // Downcast this to a Derived class instance                                                                                                                   
    auto pint = std::make_shared<int>(0);            // Define a pointer to an integer                                                                                                                              

    std::cout << "assigning pint" << std::endl;                                                                                                                                                                     
    pD->wp = pint;                                   //Attempt to assign member of Derived                                                                                                                                                                 
    std::cout << "Did not segfault" << std::endl;                                                                                                                                                                   

    return 0;                                                                                                                                                                                                       
}

【问题讨论】:

  • 您的static_pointer_cast 具有未定义的行为,当然,因为pB 实际上并不指向pD 类型的对象。
  • 我明白了。我显然误解了std::static_pointer_cast 的作用。你会如何建议我实现我想要的,即将底层的Base“升级”到Derived,最后产生std::shared_ptr&lt;Derived&gt;
  • 问题是你实际上是在构造一个Base,所以当你将它转换为Derived(有效)你在访问它时会得到未定义的行为,因为Derived的内存实际上从来没有分配。在这种情况下,您会遇到段错误。
  • 确实如此,虽然我不确定它指的是boost::shared_ptrs
  • @WilliamHandley:“我明显误解了 std::static_pointer_cast 的作用是什么。” 仅供参考:static_pointer_cast 的重点是完全按照 static_cast如果您使用的是非智能指针,就可以了。因此,如果 Base *pB = new Base; Derived *pD = static_cast&lt;Derived*&gt;(pB) 不合法(实际上不合法),那么 shared_ptr 等效项也不合法。

标签: c++ c++11 casting shared-ptr weak-ptr


【解决方案1】:

这可以编译并且可以工作,但我不确定它是否是“好”c++11

#include<iostream>                                                                                                                                                                               
#include<memory>                                                                                                                                                                                 

struct Base {};                                                                                                                                                                                  

struct Derived : Base                                                                                                                                                                            
{                                                                                                                                                                                                
    Derived(std::shared_ptr<Base> b) : Base{*b} {}                                                                                                                                               
    std::weak_ptr<int> wp;                                                                                                                                                                       
};                                                                                                                                                                                               

int main()                                                                                                                                                                                       
{                                                                                                                                                                                                
    auto pB = std::make_shared<Base>();              // Create a pointer to Base class instance                                                                                                  
    auto pD = std::make_shared<Derived>(pB);                                                                                                                                                     
    auto pint = std::make_shared<int>(0);            // Define a pointer to an integer                                                                                                           

    std::cout << "assigning pint" << std::endl;                                                                                                                                                  
    pD->wp = pint;                                                                                                                                                                               
    std::cout << "Did not segfault" << std::endl;                                                                                                                                                

    return 0;                                                                                                                                                                                    
}          

【讨论】:

  • 是的,这是合法的。但是很不清楚。如果您想移动数据,该代码将无法解决(它会创建一个副本)。
猜你喜欢
  • 2013-02-06
  • 2017-01-18
  • 1970-01-01
  • 2018-02-25
  • 1970-01-01
  • 1970-01-01
  • 2011-04-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多