2017-07-28 46 views
1

我爲我的Qt項目使用共享指針,但是當我通過共享指針調用setLayout()時,我得到了分段錯誤。std :: shared_ptr在與Qt的getter函數中刪除

我打電話這樣說:

model->getBody()->setLayout(layoutTemplate.get()); 

getBody()返回std::shared_ptr功能:

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

我嘗試使用QSharedPointer代替std::shared_ptr,但是這給了我同樣的結果。

爲什麼我的指針被刪除?

+3

由於'shared_ptr'只會在下一次嘗試使用'ui-> body'時停留在該語句的末尾,因此它將被刪除。 –

+0

謝謝,所以我無法用getter返回shared_ptr? – LilianBr

+0

爲什麼你需要'shared_ptr'? – vahancho

回答

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 a shared_ptr,然後返回該對象而不是其主體。然後,讓呼叫者通過返回的shared_ptr<UI>訪問主體。

2

由於shared_ptr的只活直到下一次您嘗試使用用戶界面 - 這句話>體也已經被刪除的終結。

您可能不想在getter中創建新的共享所有權。相反,無論什麼都應該作爲shared_ptr存在,並且getter可以返回(shared_ptr的)副本。

或者,在您未轉讓所有權的情況下,原始指針(其中body可以爲null)或引用(body不能爲null)更合適。指針/引用通常不會超出指向/引用對象的警告仍然適用。

  1. 並且沒有其副本已取得