1

一个对象memory有一个带有签名的方法

BinaryPattern const& getPattern(unsigned int index) const;

我在以下 for 循环中使用它:

for (unsigned int k = 0; k < memory->size(); k++) {
    const BinaryPattern s = memory->getPattern(k);
    w += s.at(i) * s.at(j);
}

这是非常缓慢的。令人惊讶的是,我发现以下内容要快得多:

for (unsigned int k = 0; k < memory->size(); k++) {
    w += memory->getPattern(k).at(i) * memory->getPattern(k).at(j);
}

“getPattern()”不做任何计算,它几乎只是返回存储在向量中的模式。

为什么当我将引用存储在变量中时速度会慢得多?我最初这样做是为了加快速度,因为我预计两次检索引用会更慢。

4

3 回答 3

9

这是因为

const BinaryPattern s = memory->getPattern(k);

通过调用对象的复制构造函数来制作对象的副本。由于您不想更改它,请改为存储参考:

const BinaryPattern& s = memory->getPattern(k);
//                 ^
//                 note this

(由于使用const引用捕获右值会延长右值的生命周期,直到引用终止,所以如果更改签名getPattern()以返回副本而不是引用,这甚至可以工作。)


在优化的构建中(您没有比较调试构建,是吗?),编译器可能能够确定对函数的两次调用

memory->getPattern(k).at(i) * memory->getPattern(k).at(j)

没有任何副作用,因此保留了对第一次调用获得的对象的引用并优化了第二次调用——到达我上面提出的代码。

显然,复制一个BinaryPattern对象的成本是不可忽视的。

于 2012-08-15T13:27:03.220 回答
3

因为您在这里创建副本

const BinaryPattern s = memory->getPattern(k);

只需更改为

const BinaryPattern &s = memory->getPattern(k);
于 2012-08-15T13:27:21.837 回答
3

在行

const BinaryPattern s = memory->getPattern(k);

创建一个新实例,BinaryPattern并将返回值getPattern复制到其中。

你可能是说

const BinaryPattern& s = memory->getPattern(k);
于 2012-08-15T13:27:25.580 回答