如果B()
调用构造函数来创建临时对象,例如在 call 中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
根本没有分配。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句