明确分享的意思是什么?

时间:2012-04-21 15:02:29

标签: c++ qt class pointers qwt

在此页面中:

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

方法

void QwtPlotCurve::setRawSamples()

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

while:

void QwtPlotCurve::setSamples()

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

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

2 个答案:

答案 0 :(得分:7)

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

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

即使您通过值传递QVector数据作为Qt中的参数,它也不会立即复制内存。如果其中一个向量发生了变化,它只会复制。

会想到在setSamples案例中说明“显式共享”的文档只是为了引起人们注意你通过引用而不是通过值传递QVectors的事实: p>

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

我也会想到他们这样做,这样如果你改变矢量中的数据(或释放它),它将影响绘图曲线所保持的数据。如果您认为向量是按值传递的(您无法判断是否只是在阅读调用点),那么您并不期望这样做。

HOWEVER 查看源代码看来,无论如何它只是制作一个隐式共享的副本。在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的简单分配。这可以追溯到普通的“隐性共享”。因此,您在传入的数据中所做的更改会被图表看到;您将支付在此类修改时制作的副本。

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

答案 1 :(得分:3)

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 = a;     b.detach(); 这有效地禁用了共享,这意味着您永远不需要调用detach()。如果有的话,请使用copy()函数:

b = a.copy();