取消引用共享指针并按引用调用
Dereferencing shared pointer and call by reference
我使用 QMapControl 的一些分支并发现了一个错误。 GeometryPointImage 有 getter 图像 const QPixmap& image() const
:
const QPixmap& GeometryPointImage::image() const
{
// Is the image pixmap currently null?
if (m_image == nullptr) { //std::shared_ptr<QPixmap> m_image;
// Have we already constructed the null image pixmap?
if (m_image_null == nullptr) { //std::unique_ptr<QPixmap> m_image_null;
// Construct the null image pixmap.
m_image_null.reset(new QPixmap);
}
// Return the null image pixmap.
return *(m_image_null.get());
} else {
// Return the image pixmap.
return *(m_image.get());
}
}
m_image
有多种setter,image()
getter用在draw()
函数中:
painter.drawPixmap(-pixmap_rect_px.rawRect().width() / 2.0, -pixmap_rect_px.rawRect().height() / 2.0, image()); // void drawPixmap(int x, int y, const QPixmap &pm)
我可以捕捉到这样的行为:draw()
函数调用 image()
取消引用共享指针,它进入 drawPixmap
和其他一些事件调用 setImage()
其中 m_image
分配给新值,共享指针的析构函数析构 drawPixmap()
引用的 QPixmap
对象,然后应用程序进入 SIGSEGV。
我认为 getter return 对共享指针所拥有的东西的引用不是这样好的做法,但是最合适的解决方案是什么?我不想复制 QPixMap
对象或将互斥体添加到 getter、setter 和 draw()
中。有没有办法延长引用对象的寿命(可能类似于 qAsConst
)?应该 getter return std::shared_ptr<QPixmap>
?
更新:
详细信息:setImage()
从主线程调用,此 setter 预计会发出信号以重绘对象。但是 QMapControl main class 也使用 QtConcurrent::run()
重绘整个场景,并且它涉及其他线程的像素图。并且线程 #1 在线程例如删除对象时删除对象。 #6(或#7)做 drawPixmap()
.
好吧,我不希望现在有人对这个问题给出另一个答案,所以让我的解决方案,它可能会帮助以后遇到这种问题的人:
std::shared_ptr<QPixmap> GeometryPointImage::image() const
{
// Is the image pixmap currently null?
if (m_image == nullptr)
{
// Have we already constructed the null image pixmap?
if (m_image_null == nullptr)
{
// Construct the null image pixmap.
m_image_null.reset(new QPixmap);
}
// Return the null image pixmap.
return std::make_shared<QPixmap>(*m_image_null.get());
}
else
{
// Return the image pixmap.
return m_image;
}
}
....
painter.drawPixmap(-pixmap_rect_px.rawRect().width() / 2.0, -pixmap_rect_px.rawRect().height() / 2.0, *image());
现在,返回 shared_ptr
会延长 QPixMap 的生命周期,即使它已被其他东西重置。此外,image()
方法仅在 class 中使用,没有从外部使用,因此很容易解决此问题。
我使用 QMapControl 的一些分支并发现了一个错误。 GeometryPointImage 有 getter 图像 const QPixmap& image() const
:
const QPixmap& GeometryPointImage::image() const
{
// Is the image pixmap currently null?
if (m_image == nullptr) { //std::shared_ptr<QPixmap> m_image;
// Have we already constructed the null image pixmap?
if (m_image_null == nullptr) { //std::unique_ptr<QPixmap> m_image_null;
// Construct the null image pixmap.
m_image_null.reset(new QPixmap);
}
// Return the null image pixmap.
return *(m_image_null.get());
} else {
// Return the image pixmap.
return *(m_image.get());
}
}
m_image
有多种setter,image()
getter用在draw()
函数中:
painter.drawPixmap(-pixmap_rect_px.rawRect().width() / 2.0, -pixmap_rect_px.rawRect().height() / 2.0, image()); // void drawPixmap(int x, int y, const QPixmap &pm)
我可以捕捉到这样的行为:draw()
函数调用 image()
取消引用共享指针,它进入 drawPixmap
和其他一些事件调用 setImage()
其中 m_image
分配给新值,共享指针的析构函数析构 drawPixmap()
引用的 QPixmap
对象,然后应用程序进入 SIGSEGV。
我认为 getter return 对共享指针所拥有的东西的引用不是这样好的做法,但是最合适的解决方案是什么?我不想复制 QPixMap
对象或将互斥体添加到 getter、setter 和 draw()
中。有没有办法延长引用对象的寿命(可能类似于 qAsConst
)?应该 getter return std::shared_ptr<QPixmap>
?
更新:
详细信息:setImage()
从主线程调用,此 setter 预计会发出信号以重绘对象。但是 QMapControl main class 也使用 QtConcurrent::run()
重绘整个场景,并且它涉及其他线程的像素图。并且线程 #1 在线程例如删除对象时删除对象。 #6(或#7)做 drawPixmap()
.
好吧,我不希望现在有人对这个问题给出另一个答案,所以让我的解决方案,它可能会帮助以后遇到这种问题的人:
std::shared_ptr<QPixmap> GeometryPointImage::image() const
{
// Is the image pixmap currently null?
if (m_image == nullptr)
{
// Have we already constructed the null image pixmap?
if (m_image_null == nullptr)
{
// Construct the null image pixmap.
m_image_null.reset(new QPixmap);
}
// Return the null image pixmap.
return std::make_shared<QPixmap>(*m_image_null.get());
}
else
{
// Return the image pixmap.
return m_image;
}
}
....
painter.drawPixmap(-pixmap_rect_px.rawRect().width() / 2.0, -pixmap_rect_px.rawRect().height() / 2.0, *image());
现在,返回 shared_ptr
会延长 QPixMap 的生命周期,即使它已被其他东西重置。此外,image()
方法仅在 class 中使用,没有从外部使用,因此很容易解决此问题。