c++ - 返回私有(private)类成员是否比使用结构并直接访问该变量慢?

标签 c++ performance class struct

假设您有一个包含私有(private)成员的类,这些成员在程序中经常被访问(例如在必须快速的循环中)。想象一下,我定义了这样的东西:

class Foo
{
public: 

    Foo(unsigned set)
        : vari(set)
    {}

    const unsigned& read_vari() const { return vari; }

private:
    unsigned vari;
};

我想这样做的原因是,一旦创建了类,“vari”就不应再更改。因此,为了尽量减少错误的发生,“这在当时看来是个好主意”。

但是,如果我现在需要调用此函数数百万次,我想知道是否存在开销和速度减慢而不是简单地使用:

struct Foo
{
    unsigned vari;
};

那么,我使用类的第一个冲动是否正确,以避免任何人在构造函数设置变量后错误地更改变量的值? 此外,这是否会以函数调用开销的形式引入“惩罚”。 (假设我在编译器中使用优化标志,例如 GCC 中的 -O2)?

最佳答案

他们应该是一样的。还记得您尝试在 vector 上使用 operator[]gdb 只是回复 optimized out 的沮丧时刻吗?这就是这里将要发生的事情。编译器不会在此处创建函数调用,而是直接访问变量。

让我们看看下面的代码

struct foo{
   int x;
   int& get_x(){
     return x;
   }   
};

int direct(foo& f){ 
   return  f.x;
}

int fnc(foo& f){ 
   return  f.get_x();
}

它是用 g++ test.cpp -o test.s -S -O2 编译的。 -S 标志告诉编译器“在适当的编译阶段后停止;不要汇编(引用自 g++ 联机帮助页)”。这是编译器给我们的:

_Z6directR3foo:
.LFB1026:
  .cfi_startproc
  movl  (%rdi), %eax
  ret 

_Z3fncR3foo:
.LFB1027:
  .cfi_startproc
  movl  (%rdi), %eax
  ret 

如您所见,在第二种情况下没有进行任何函数调用,它们是相同的。这意味着使用访问器方法没有性能开销。

奖励:如果关闭优化会发生什么?同样的代码,结果如下:

_Z6directR3foo:
.LFB1022:
  .cfi_startproc
  pushq %rbp
  .cfi_def_cfa_offset 16
  .cfi_offset 6, -16
  movq  %rsp, %rbp
  .cfi_def_cfa_register 6
  movq  %rdi, -8(%rbp)
  movq  -8(%rbp), %rax
  movl  (%rax), %eax
  popq  %rbp
  .cfi_def_cfa 7, 8
  ret

_Z3fncR3foo:
.LFB1023:
  .cfi_startproc
  pushq %rbp
  .cfi_def_cfa_offset 16
  .cfi_offset 6, -16 
  movq  %rsp, %rbp
  .cfi_def_cfa_register 6
  subq  $16, %rsp
  movq  %rdi, -8(%rbp)
  movq  -8(%rbp), %rax
  movq  %rax, %rdi
  call  _ZN3foo5get_xEv    #<<<call to foo.get_x()
  movl  (%rax), %eax
  leave
  .cfi_def_cfa 7, 8
  ret

如您所见,在没有优化的情况下,结构比访问器快,但是谁在没有优化的情况下发布代码呢?

关于c++ - 返回私有(private)类成员是否比使用结构并直接访问该变量慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23125713/

相关文章:

c++ - 结合静态断言和断言?

c++ - 对静态变量的 undefined reference

c# - 这个算法有什么缺陷?

python - 有没有办法在 Python 中创建类属性?

c++ - 奇怪的! linux 和 windows sprintf float 到文件

python - 为什么这个列表理解比 Python 中使用 for 循环进行条件初始化慢?

.net - 数据适配器 : Is it possible to fill a Collection-Type instead of a DataTable/DataSet?

c++ - 定义类构造器

html - BEM CSS类命名

c++ - 在 C 或 C++ 中打印调用堆栈