如果调用了构造函数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
的实例,包括为name
分配存储空间?
答案 0 :(得分:3)
与其他任何函数一样,编译器可能会完全删除对构造函数的调用。虽然B的实例对于使代码在语义上正确是必要的,但这并不意味着在编译后它必须存在(作为一块内存)。还请记住,对构造函数的调用与分配不同。
据我所知,问题是编译器是否也可以删除堆分配(如使用new/delete
运算符)?通常,编译器很难进行副作用操作。但是,分配似乎是一个例外:Can the compiler optimize from heap to stack allocation?只要没有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
根本没有分配。