【问题标题】:What does explicitly shared mean?明确共享是什么意思?
【发布时间】:2012-04-21 15:02:29
【问题描述】:

在此页面中:

http://qwt.sourceforge.net/class_qwt_plot_curve.html#afd13c94e23520dacbc37b4d0fd036a8b

方法

void QwtPlotCurve::setRawSamples()

只是将数据的地址保存在QwtPlotCurve中,这正是我想要的效率。

同时:

void QwtPlotCurve::setSamples()

使用QVector,更方便。但它只是“明确共享”。那是什么意思?是否像第一个一样保存指针?

我需要每 50 毫秒在图中添加一个点。深度复制数据不是最好的解决方案!!!建议?

【问题讨论】:

  • 50 毫秒通常足够做很多事情。

标签: c++ qt class pointers qwt


【解决方案1】:

它与 Qt 的“隐式共享”概念并列:

http://doc.qt.io/archives/qt-4.7/implicit-sharing.html

即使你在 Qt 中通过值传递一个 QVector 的数据作为参数,它也不会立即复制内存。仅当其中一个向量发生更改时才会进行复制。

会认为在 setSamples 案例中说“显式共享”的文档只是为了提请注意您通过引用而不是值传递 QVectors 的事实:

void QwtPlotCurve::setSamples(
    const QVector< double > &xData,
    const QVector< double > &yData 
)

我也会认为他们这样做是为了如果您更改向量中的数据(或释放它),它将影响绘图曲线保存的数据。如果您认为向量是按值传递的,您不会想到会发生这种情况(您无法判断您是否只是在阅读调用站点)。

然而查看源代码,它似乎只是在制作一个隐式共享的副本。在qwt_plot_curve.cpp 我们有:

/*!
   \brief Initialize data with x- and y-arrays (explicitly shared)

   \param xData x data
   \param yData y data
   \sa QwtPointArrayData
*/
void QwtPlotCurve::setSamples( const QVector<double> &xData,
    const QVector<double> &yData )
{
    setData( new QwtPointArrayData( xData, yData ) );
}

我们可以看到 QwtPointArrayData 在qwt_point_data.h 中声明如下:

class QWT_EXPORT QwtPointArrayData: public QwtSeriesData<QPointF>
{
public:
    QwtPointArrayData( const QVector<double> &x, const QVector<double> &y );
    QwtPointArrayData( const double *x, const double *y, size_t size );

    virtual QRectF boundingRect() const;

    virtual size_t size() const;
    virtual QPointF sample( size_t i ) const;
    const QVector<double> &xData() const;
    const QVector<double> &yData() const;

private:
    QVector<double> d_x;
    QVector<double> d_y;
};

qwt_point_data.cpp 中的构造函数代码只是对d_xd_y 的简单赋值。这可以追溯到普通的 ol' 隐式共享。因此,您对传入的数据所做的更改将不会被绘图看到;您将支付进行此类修改时制作的副本的费用。

如果他们只是要这样做,那么为什么他们费心传递一个 const 引用(而不仅仅是按值)对我来说是个谜。这里唯一的“分享”似乎是隐含的,所以我不知道“明确分享”的评论应该是什么意思。

【讨论】:

  • 这是否意味着如果我向数组 xData、yData 添加一个点,我会立即看到它对绘图的影响?这正是我想要的!!!!!!!!!!我打算使用 FIFO 之类的东西来绘制我添加到这些数组中的点。这就是我要找的吗?
  • 如果您对向量进行细微修改并希望避免复制,您可以尝试myPlot-&gt;setSamples(QVector&lt;double&gt;(), QVector&lt;double&gt;()); 之前对传递的向量进行任何更改in. 这将使情节释放它所持有的隐式共享引用,因此您不必为修改时发生的副本付费。可以帮忙...[耸肩]
  • 非常感谢。但是每次添加一个点时调用 setRawSamples() 不是更容易吗?
  • 嗯是的......但我都专注于查看 QVector 方法。 :) 您仍然可以使用 QVector 及其 data()setRawSamples,只要您在添加点时要小心,并且不允许它在 Qwt 可能正在查看的时刻进行重新分配过时的指针...
  • 我做到了,它奏效了。但是,我必须每 10 个点重新绘制一次(我必须将采样降低 10 倍),这是可以接受的:-)...我使用的是 QVector::front() 的参考,我是在事物的开头调用reserve,这样我就可以避免重新分配;-),每次我添加一个点时,我都会使用函数setRawSamples()进行更新。所以现在一切都很完美!!感谢大家的帮助!
【解决方案2】:

取自http://doc.qt.io/archives/qq/qq02-data-sharing-with-class.html

通过显式共享,在修改对象之前调用 detach() 是用户的责任,而不是类的责任。如果用户忘记调用 detach(),共享相同数据的所有对象都会修改其状态,这是一个非常危险的副作用。

明确共享的类在语义上类似于指针。比较左边的代码,它使用 int *,和右边的代码,它使用一个虚构的显式共享 Int 类:

int *a = new int( 111 );    Int a( 111 );
int *b = a;                 Int b = a;
*b = 222;                   b = 222;
qDebug( "%d", *a );         qDebug( "%d", (int) a );

两个程序都打印 222。对于左侧的代码,这是我们所期望的(指针语法是一个很大的提示),但对于右侧的代码,它却是一个令人不快的惊喜。显式共享可能会解决所有权问题,但其误导性语法使其无法替代指针。

Qt 类 QMemArray、QImage 和 QMovie 的明确共享归功于历史。为了保持头脑清醒,在处理明确共享的类时,请选择以下准则之一:

避免显式共享类。 每次要修改对象时调用 detach(),除非您确定对象没有副本。这是非常容易出错的。 每次复制对象时调用 detach(): b = 一个; b.分离(); 这有效地禁用了共享,并且意味着您永远不需要调用 detach()。如果可用,请使用 copy() 函数:

b = a.copy();

【讨论】:

  • 实际上我很困惑......我想动态地向我的向量添加点并避免所有类型的复制,当我添加一个点时,我想自动查看它对绘图的影响! !!在这种情况下你有什么建议?
  • 这基本上意味着它不会复制,它会取实际变量。如果您需要立即查看它,请在添加点后调用绘图的任何更新函数。
  • @chris 似乎并非如此。请参阅我对源代码调查的回答...这可能是未同步的过时评论(?)关于此的对话:comments.gmane.org/gmane.comp.graphics.qwt.general/3228
  • @HostileFork 啊,这真的很有帮助>.>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-12
  • 1970-01-01
  • 1970-01-01
  • 2014-09-20
  • 2014-12-24
  • 2012-02-27
相关资源
最近更新 更多