编译器会优化构造函数调用吗

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

完全没有分配。