C ++ - 循环效率:存储类成员的临时值Vs指向此成员的指针

时间:2016-06-15 12:25:29

标签: c++ class loops pointers

在类方法中,我正在访问私有属性 - 或嵌套类的属性。而且,我正在循环这些属性。

我想知道在时间(和内存)方面最有效的方式是什么:

  • 复制属性并在循环中访问它们
  • 访问循环中的属性
  • 或者可能在属性
  • 上使用迭代器

我觉得我的问题与Efficiency of accessing a value through a pointer vs storing as temporary value有关。但就我而言,我只需要访问一个值,而不是更改它。

示例

给出两个班级

class ClassA
{
 public:
       vector<double> GetAVector() { return AVector; }           

 private:
       vector<double> m_AVector;
}

class ClassB 
{
 public:
    void MyFunction();

 private:
    vector<double> m_Vector;
    ClassA m_A;
}

我。我应该这样做:

1

void ClassB::MyFunction()
{
    vector<double> foo;
    for(int i=0; i<... ; i++)
    {
         foo.push_back(SomeFunction(m_Vector[i]));
    }
    /// do something ...
}

2

void ClassB::MyFunction()
{
    vector<double> foo;
    vector<double> VectorCopy = m_Vector;
    for(int i=0; i<... ; i++)
    {
         foo.push_back(SomeFunction(VectorCopy[i]));
    }
    /// do something ...
}

第3

void ClassB::MyFunction()
{
    vector<double> foo;
    for(vector<double>::iterator it = m_Vector.begin(); it != m_Vector.end() ; it++)
    {
         foo.push_back(SomeFunction((*it)));
    }
    /// do something ...
}

II。如果我没有循环m_vectorm_A.GetAVector()怎么办?

P.S。 :我通过其他帖子了解到,首先对微观优化没有用处,但我的问题与实际发生的事情和应该做的事情更相关 - 标准(和编码风格)

3 个答案:

答案 0 :(得分:2)

您很幸运:您实际上可以通过在编译器和操作系统上尝试每种方法来确定答案,并为每种方法计时以查看需要多长时间。

这里没有通用的答案,适用于太阳第三颗行星上存在的每个可以想象的C ++编译器和操作系统。每个编译器和硬件都不同,并且具有不同的运行时特性。即使同一编译器的不同版本也经常会导致可能影响性能的不同运行时行为。更不用说各种编译和优化选项。既然你甚至没有指定你的编译器和操作系统,那么这里没有权威的答案。

虽然对于某些类型的问题而言,对于大多数用例来说,可以高度确定地实现最佳实施,但对于大多数用例来说,这不是其中之一。 。你能得到答案的唯一方法就是自己弄清楚,自己尝试每种方法,分析和比较结果。

答案 1 :(得分:0)

我可以明确地说2.效率低于1.复制到本地副本,然后就像访问堆栈变量时原来只有潜在一样才能访问它比访问一个成员更快,但事实并非如此,所以它不是(如果你明白我的意思)。

选项3.比较复杂,因为它取决于iter()方法(和end()的实现,每个循环可以调用一次)与operator []方法的实现相比。我可能会激怒一些C ++顽固分子并说有一个选项4:向Vector询问指向数组的指针并直接使用指针或数组索引。这可能比其中任何一个都快!

至于II,那里有双重间接。一个好的编译器应该发现并缓存结果以供重复使用 - 但是否则它只会比不这样做慢一点:再次,取决于你的编译器。

答案 2 :(得分:-1)

如果没有优化,选项2在每个可以想象的平台上都会变慢,因为它会产生向量的副本,并且访问时间对于局部变量和类成员来说是相同的。

通过优化,取决于SomeFunction,选项2的性能可能相同或更差。如果编译器可以看到SomeFunction不修改它的参数,或者它的签名保证,则会发生相同的性能该参数不会被修改 - 在这种情况下,编译器可以完全优化副本。否则,副本将保留。