现代C++编译器是否优化了对类中同一数据成员的重复访问?

Do modern C++ compilers optimize away repeated accesses to the same data member of a class?

本文关键字:数据成员 访问 是否 编译器 C++ 优化 现代      更新时间:2023-10-16

考虑:

class A
{
public:
const int& my_int_member() const { return my_int_member; }
const double& my_double_member const {return my_double_member; }
private:
int my_int_member;
double my_double_member;
};
class B
{
public:
const A& my_A_member() const { return my_A_member; }
private:
A my_A_member;
};

现代 c++ 编译器(例如 msvc、clang、gcc)设置了每个编译器提供的最大优化级别,通常识别并优化对同一数据成员的重复访问,如下所示:

B b;
do_stuff(b.my_A_member().my_double_member(), b.my_A_member().my_int_member());
double c = b.my_A_member().my_double_member() + b.my_A_member().my_int_member();

也就是说,他们是否意识到他们可以重用相同的引用,或者他们只是再次访问?

如果定义是可见的,并且如果编译器可以证明它做同样的事情(使用 as-if 规则进行优化)(这比我们可以做的更棘手,使用别名、全局访问,...),它可以做到(并且可能做到)。

但是想象一下,我们将您的示例修改为(b 不再是本地的,而是作为参数给出的):

void foo(B& b)
{
do_stuff(b.my_A_member().my_double_member(), b.my_A_member().my_int_member());
double c = b.my_A_member().my_double_member() + b.my_A_member().my_int_member();
}

do_stuff可以修改全局B这将是foo的参数。 没有定义,答案是肯定的。因此,编译器必须在调用b.my_A_member()后重新加载do_stuff

为了可读性,我无论如何都会这样做:

B b;
const auto& a = b.my_A_member();
do_stuff(a.my_double_member(), a.my_int_member());
double c = a.my_double_member() + a.my_int_member();