为什么优化器不优化这段代码?
Why doesn't the optimizer optimize this code?
使用最大优化设置编译和运行此代码似乎给出了相同的结果。
#include <stdio.h>
class A
{
public:
A() { }
const int* begin() const { return a; };
const int* end() const { printf("end\n"); return a + 3; };
bool isTrue() const { return true; }
int a[4];
};
const A a{};
class B
{
public:
const A& operator[](size_t) const { printf("B called\n"); return a; }
};
int main()
{
const B b{};
if (!b[0].isTrue()) return -1;
for (const auto& x : b[0]) printf("%d\n", x);
}
我在 B 类型的常量对象上调用 b[0] 两次,其中 operator[] return 是 A 类型的常量对象。
为什么“B called”被打印了两次?为什么代码不能在旁边保存 b[0] 而在其上保存 运行 不同的功能? (由于函数是 const 函数,它们将 return 相同的结果...)
Why does "B called" get printed twice?
对于初学者来说,因为您在 main 中引用了两次 b[0]
。并且由于运算符函数中的 printf
语句指示访问 b[0]
存在副作用。因此编译器不能假定您的 printf 仅用于调试 - 它必须为每次调用调用一次。
使用 godbolt,如果我们删除 printf 语句并进行评估,我们可以看到代码经过大量优化,无需任何调用即可打印 3 次 0
。
operator[]
和其他函数一样是普通函数,由于 C++ 没有纯函数的概念,编译器必须假设每个函数都有副作用。其中一个副作用是您的 printf
调用。如果您 优化 取消对 operator[]
的调用之一,您的程序行为可能会改变(这里它只会打印一次而不是两次)。想象一下,您将调用数据库或其他重要的东西而不是 printf
。如果它只是优化,那就太糟糕了。
另请注意,const
成员函数与纯函数不同。 const
表示它不能修改您调用成员函数的实例,但您仍然可以更改全局变量。而且您甚至不能保证 const
成员函数不会更改实例的状态,因为您可以在某些条件下丢弃 const
。
使用最大优化设置编译和运行此代码似乎给出了相同的结果。
#include <stdio.h>
class A
{
public:
A() { }
const int* begin() const { return a; };
const int* end() const { printf("end\n"); return a + 3; };
bool isTrue() const { return true; }
int a[4];
};
const A a{};
class B
{
public:
const A& operator[](size_t) const { printf("B called\n"); return a; }
};
int main()
{
const B b{};
if (!b[0].isTrue()) return -1;
for (const auto& x : b[0]) printf("%d\n", x);
}
我在 B 类型的常量对象上调用 b[0] 两次,其中 operator[] return 是 A 类型的常量对象。
为什么“B called”被打印了两次?为什么代码不能在旁边保存 b[0] 而在其上保存 运行 不同的功能? (由于函数是 const 函数,它们将 return 相同的结果...)
Why does "B called" get printed twice?
对于初学者来说,因为您在 main 中引用了两次 b[0]
。并且由于运算符函数中的 printf
语句指示访问 b[0]
存在副作用。因此编译器不能假定您的 printf 仅用于调试 - 它必须为每次调用调用一次。
使用 godbolt,如果我们删除 printf 语句并进行评估,我们可以看到代码经过大量优化,无需任何调用即可打印 3 次 0
。
operator[]
和其他函数一样是普通函数,由于 C++ 没有纯函数的概念,编译器必须假设每个函数都有副作用。其中一个副作用是您的 printf
调用。如果您 优化 取消对 operator[]
的调用之一,您的程序行为可能会改变(这里它只会打印一次而不是两次)。想象一下,您将调用数据库或其他重要的东西而不是 printf
。如果它只是优化,那就太糟糕了。
另请注意,const
成员函数与纯函数不同。 const
表示它不能修改您调用成员函数的实例,但您仍然可以更改全局变量。而且您甚至不能保证 const
成员函数不会更改实例的状态,因为您可以在某些条件下丢弃 const
。