std::shared_ptr 在 Qt 的 getter 函数中删除
std::shared_ptr deleted in a getter function with Qt
我正在为我的 Qt 项目使用共享指针,但是当我通过共享指针调用 setLayout()
时出现分段错误。
我是这样称呼它的:
model->getBody()->setLayout(layoutTemplate.get());
函数getBody()
returns一个std::shared_ptr
:
std::shared_ptr<QWidget> MainTemplate::getBody()
{
return std::shared_ptr<QWidget>(ui->body);
}
我尝试使用 QSharedPointer
而不是 std::shared_ptr
,但结果相同。
为什么我的指针被删除了?
Since the shared_ptr only lives until the end of that statement1 the next time you try to use ui->body it will have been deleted.
您可能不想在 getter 中创建新的共享所有权。相反,得到的任何东西都应该作为 shared_ptr 存在,而 getter 可以 return 一个副本(shared_ptr)。
或者,在您不转移所有权的情况下,原始指针(其中 body 可以为 null)或引用(其中 body 不能为 null)更合适。 pointers/references 不会超过 pointed/referenced 对象的通常注意事项仍然适用。
- 并且没有复制它
智能指针表示对象的所有权。 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
。一般来说,你想要做的只是通过非常量引用 return body
,或者只是不 return 它并为其参数提供 setter 函数。
QWidget& MainTemplate::getBody()
{
return ui->body;
}
然而,如果某些原因决定 body 需要能够比它的 class 更长寿(值得怀疑,除非做出有问题的设计决定),您需要使 body 本身成为 shared_ptr
并且return 按值计算。这将创建 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;
}
}
同样,如果您的 classes 已经以实用的方式定义,我认为不需要这样做。此外,如果 ui
不属于 class,则可以将 ui
设为 shared_ptr
,而将 return 设为 return 而不是其主体。然后,让调用者通过 returned shared_ptr<UI>
.
访问正文
我正在为我的 Qt 项目使用共享指针,但是当我通过共享指针调用 setLayout()
时出现分段错误。
我是这样称呼它的:
model->getBody()->setLayout(layoutTemplate.get());
函数getBody()
returns一个std::shared_ptr
:
std::shared_ptr<QWidget> MainTemplate::getBody()
{
return std::shared_ptr<QWidget>(ui->body);
}
我尝试使用 QSharedPointer
而不是 std::shared_ptr
,但结果相同。
为什么我的指针被删除了?
Since the shared_ptr only lives until the end of that statement1 the next time you try to use ui->body it will have been deleted.
您可能不想在 getter 中创建新的共享所有权。相反,得到的任何东西都应该作为 shared_ptr 存在,而 getter 可以 return 一个副本(shared_ptr)。
或者,在您不转移所有权的情况下,原始指针(其中 body 可以为 null)或引用(其中 body 不能为 null)更合适。 pointers/references 不会超过 pointed/referenced 对象的通常注意事项仍然适用。
- 并且没有复制它
智能指针表示对象的所有权。 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
。一般来说,你想要做的只是通过非常量引用 return body
,或者只是不 return 它并为其参数提供 setter 函数。
QWidget& MainTemplate::getBody()
{
return ui->body;
}
然而,如果某些原因决定 body 需要能够比它的 class 更长寿(值得怀疑,除非做出有问题的设计决定),您需要使 body 本身成为 shared_ptr
并且return 按值计算。这将创建 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;
}
}
同样,如果您的 classes 已经以实用的方式定义,我认为不需要这样做。此外,如果 ui
不属于 class,则可以将 ui
设为 shared_ptr
,而将 return 设为 return 而不是其主体。然后,让调用者通过 returned shared_ptr<UI>
.