使用Qt在getter函数中删除了std :: shared_ptr

时间:2017-07-28 09:31:37

标签: c++ qt shared-ptr

我正在为我的Qt项目使用共享指针,但是当我通过共享指针调用<div class="container"> <div class="block left"> <h5>New</h5> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc sollicitudin purus sapien, a scelerisque neque.</p> </div> <div class="block right"> <h5>Heading</h5> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc sollicitudin purus sapien.</p> </div> <div class="block left"> <h5>Cras conva</h5> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc sollicitudin purus sapien.</p> </div> <div class="block right"> <h5>Cras nita</h5> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc sollicitudin purus sapient.</p> </div> </div>时,我遇到了分段错误。

我这样称呼它:

setLayout()

函数 model->getBody()->setLayout(layoutTemplate.get()); 返回getBody()

std::shared_ptr

我尝试使用std::shared_ptr<QWidget> MainTemplate::getBody() { return std::shared_ptr<QWidget>(ui->body); } 代替QSharedPointer,但这给了我相同的结果。

为什么我的指针被删除?

2 个答案:

答案 0 :(得分:2)

  

由于shared_ptr只会在下一次尝试使用ui-&gt; body时直到该语句的结尾 1 ,否则它将被删除。

您可能不希望在getter中创建新的共享所有权。相反,任何得到的都应该作为shared_ptr存在,并且getter可以返回一个副本(shared_ptr)。

或者,在您不转移所有权的情况下,原始指针(其中body可以为null)或引用(其中body不能为null)更合适。指针/引用的常见警告仍然适用于指向/引用的对象。

  1. 并没有制作任何副本

答案 1 :(得分:2)

智能指针代表对象的所有权shared_ptr特别代表一个由多个实体拥有的对象,并且必须存在,直到每个人都使用它为止。每当指向一个对象的最后一个shared_ptr被销毁时,它指向的对象也会被销毁。正确使用shared_ptr是:

std::shared_ptr<T> ptr_a(new T); // Create a T and immediately pass it to shared_ptr
std::shared_ptr<T> ptr_b = std::make_shared<T>(); // Same effect but more efficient

ptr_a = ptr_b; // smart pointer to smart pointer assignment (never existing raw to smart)
ptr_a.reset(new T);            // This is fine.
ptr_a = std::make_shared<T>(); // Same as previous line. Again more efficient

//... eventually ptr_a and ptr_b go out of scope and handle deleting their objects

请注意,在所有重新分配的示例中,ptr_a检查了引用计数并删除了保留的对象(如果它是指向它的最后一个shared_ptr

通常,您只想在创建时将原始指针传递给智能指针。您所做的是将对象的所有权传递给临时智能指针。在声明之后,临时shared_ptr被销毁,并且由于没有制作它的副本,它认为它应该销毁ui->body。通常你想要做的只是通过非const引用返回body,或者只是不返回它并为其参数提供setter函数。

QWidget& MainTemplate::getBody()
{
   return ui->body;
}

但是,如果有某种原因要求身体需要能够超过其阶级(可疑,除非已经做出可疑的设计决定),你需要将身体本身设为shared_ptr并按值返回。这将创建shared_ptr的副本,并保证最后一个将销毁该对象。但是你必须在构造完成后不要使用原始指针,你不能手动尝试删除它。

UI {    // whatever class MainTemplate::ui points to
private:
    std::shared_ptr<<QWidget> body;
...
}

MainTemplate {
public:
    std::shared_ptr<QWidget> MainTemplate::getBody()
    {
        return ui->body;
    }
}

同样,如果您的课程以实际方式定义,我认为不需要这样做。此外,如果ui不属于某个类,则可以使shared_ptr成为shared_ptr<UI>,并返回该值而不是其正文。然后,让调用者通过返回的inputs访问正文。