编译器会优化构造函数调用吗
will compiler optimize out constructor call
如果调用构造函数B()
来创建临时对象,例如在调用 f(B().name())
中,是否总是会执行 B
的构造,或者是否允许编译器并能够优化对象创建过程中不必要的分配?
具体示例:
class A {
public:
virtual std::string name() = 0;
};
class B : public A {
public:
std::string name() final { return "MyClassName"; }
// cannot be made static, because at some places we need
// the polymorphic call from A-pointers
private:
int data;
...
// members that require heap allocation
};
int main() {
std::cout << "Class B is named " << B().name() << std::endl;
}
最后一条语句是否会实际创建 B
的实例,包括 B().data
的存储分配?
编译器可以像任何其他函数一样完全删除对构造函数的调用。虽然 B 的实例对于代码在语义上是正确的是必要的,但这并不意味着在编译之后它需要存在(作为一块内存)。还要记住,对构造函数的调用与分配不同。
据我所知,问题是编译器是否也可以删除堆分配(如 new/delete
运算符的使用)?通常,编译器很难处理副作用操作。然而,分配似乎是一个例外: 只要 new/delete
运算符没有超载。
一个具体的例子是这样的:
class A {
public:
virtual int get() = 0;
virtual ~A() {};
};
class B : public A {
public:
int get() { return 5; }
~B() {
delete ptr;
}
private:
int data;
int* ptr = new int;
};
int foo() {
return B().get();
}
在我尝试过的所有编译器(gcc 和 clang,X64,完全优化)下生成简单
foo():
mov eax, 5
ret
完全没有分配。
如果调用构造函数B()
来创建临时对象,例如在调用 f(B().name())
中,是否总是会执行 B
的构造,或者是否允许编译器并能够优化对象创建过程中不必要的分配?
具体示例:
class A {
public:
virtual std::string name() = 0;
};
class B : public A {
public:
std::string name() final { return "MyClassName"; }
// cannot be made static, because at some places we need
// the polymorphic call from A-pointers
private:
int data;
...
// members that require heap allocation
};
int main() {
std::cout << "Class B is named " << B().name() << std::endl;
}
最后一条语句是否会实际创建 B
的实例,包括 B().data
的存储分配?
编译器可以像任何其他函数一样完全删除对构造函数的调用。虽然 B 的实例对于代码在语义上是正确的是必要的,但这并不意味着在编译之后它需要存在(作为一块内存)。还要记住,对构造函数的调用与分配不同。
据我所知,问题是编译器是否也可以删除堆分配(如 new/delete
运算符的使用)?通常,编译器很难处理副作用操作。然而,分配似乎是一个例外:new/delete
运算符没有超载。
一个具体的例子是这样的:
class A {
public:
virtual int get() = 0;
virtual ~A() {};
};
class B : public A {
public:
int get() { return 5; }
~B() {
delete ptr;
}
private:
int data;
int* ptr = new int;
};
int foo() {
return B().get();
}
在我尝试过的所有编译器(gcc 和 clang,X64,完全优化)下生成简单
foo():
mov eax, 5
ret
完全没有分配。