QPainter如何传输? (从工厂函数中移动一个对象)

Posted

技术标签:

【中文标题】QPainter如何传输? (从工厂函数中移动一个对象)【英文标题】:How to transfer QPainter? (move an object from a factory function) 【发布时间】:2017-09-05 07:39:08 【问题描述】:

在一个Qt相关的代码中,我尝试通过以下方法减少一些重复的行:

QPainter createPainter(const QColor& color)

  QPainter painter(&m_image);
  painter.setBrush(color);
  painter.setPen(color);
  return painter;

但是QPainter 的复制ctor 被明确删除。在 c++11 中应该不是问题,但遗憾的是它既不是可移动的。这是什么原因,还是只是 API 缺陷? createPainter 是不是很好的解决方案(除了提供move-ctor)?

它可以接受 QPainter 引用,但这会降低方法的含义,并且会给调用者的代码增加噪音。 它可以将unique_ptr 返回到QPainter,但会引入堆分配开销。 ...还有其他想法吗?

感谢您的回复!

【问题讨论】:

为什么不使用指针?喜欢:QPointer *p = new QPainter(&m_image); ... return p;? 我不想在堆上分配对象,只是为了提取三行代码。 (在那种情况下,我会使用智能指针确保在任何情况下都能正确释放画家) 如果您要转移对象的所有权或以其他方式处理它,使用智能指针是有意义的。我看你这里不需要它。不要以为使用“智能”指针会让你的代码更智能。 实际上返回的指针必须是deleted 有一个名字:所有权转移。返回原始拥有指针很容易出错。这是类似 C 的方式,但在 C++ 中不是惯用的。 @titapo 检查我的编辑。它解决了你的问题。 【参考方案1】:

一个技巧是通过常量引用返回:

选项 1:

QPainter createPainter(const QColor& color) //definitely return by value

  QPointer painter(&m_image);
  painter.setBrush(color);
  painter.setPen(color);
  return painter;

然后这样做:

const QPainter& painter = createPainter(const QColor& color);

根据 C++ 标准,这保证不会发生复制,但会延长返回值的寿命。

选项 2:

用户共享或唯一指针。我知道你说他们有开销,但这没什么,假设你没有开发游戏引擎并且这是主要管道(我确定你没有在这样的游戏引擎中使用 Qt)。

选项 3:

如果这些都不能让你满意,我会建议我讨厌的解决方案,只是为了完整性。使用宏!

#define CreatePainter(painter_name) \
QPointer painter_name(&m_image);    \
painter_name.setBrush(color);       \
painter_name.setPen(color);      

使用它:

CreatePainter(painter);
painter.begin(); 
//...

编辑:

选项 4: 我刚刚得知(感谢 Quentin)这是合法的:

QPainter createPainter(const QColor& color) //definitely return by value

  QPointer painter(&m_image);
  painter.setBrush(color);
  painter.setPen(color);
  return painter;

然后这个:

QPainter&& painter = createPainter(const QColor& color);

检查参考here。这是一个新的 C++11 解决方案,可以延长对象的生命周期而不使其成为 const。

【讨论】:

我喜欢选项 1!不幸的是,绘图是一个非常量操作,因此在当前情况下它不起作用。 @titapo 那么我要告诉你世界上最糟糕的建议:使用const_cast(不!只是在开玩笑:))。我看到的唯一合法的解决方案是宏。 如果函数按值返回对象,如何避免复制(选项 1)? @vahancho 自己试试。这是标准的一部分。人们因此多次攻击我,因为它非常不直观,但它存在于 C++ 中。它被一些“最重要的常量”调用。 Check this. @TheQuantumPhysicist,我确实没有攻击你。刚问了一个问题。现在我也明白了,谢谢。【参考方案2】:

想法一样

struct ColoredPainter : public QPainter 
ColoredPainter (device, color) : QPainter (device)
setBrush(color);
setPen(color);
;

...

ColoredPainter painter(m_Image, color);

但我不喜欢这个主意。看起来重复的代码部分看起来是一样的,但把它放到独立块中是没有意义的。这种类甚至函数都很难理解。

【讨论】:

以上是关于QPainter如何传输? (从工厂函数中移动一个对象)的主要内容,如果未能解决你的问题,请参考以下文章

使用 PySide 时,如何有效地将数据从 NumPy 数组传输到 QPolygonF?

如何使用 QPainter 在 QOpenGLWidget 中进行叠加 [关闭]

如何使用 QPropertyAnimation 和 QPainter 绘制弧线

如何销毁 QPainter 对象/摆脱 drawText() 内存泄漏?

ETL - 自动从一个数据库到另一个数据库的数据传输

如何在paintEvent之外获取QPainter的字体度量?