除了复制省略之外,是否还有其他机制可以优化 C++ 中的过度构造?

Are there any mechanisms other than copy elision that can optimize out excessive construction in C++?

我的函数有一个 switch-case 语句。有一个对象仅在其某些分支中使用。我能不能把这个对象的初始化放在switch-case语句之前,并期望它只在实际使用时才被创建。

我的意思是,这段代码在性能上有什么不同吗:

void someFunc( SomeEnum someEnum, Parameter parameter )
{
    Object object( parameter );
    
    switch( someEnum )
    {
    case SomeEnum::A:
        otherFunc( object );
        break;
        
    case SomeEnum::B:
        otherFunc( object );
        break;
        
    case SomeEnum::C:
        anotherFunc();
        break;
    }
}

还有这个:

void someFunc( SomeEnum someEnum, Parameter parameter )
{   
    switch( someEnum )
    {
    case SomeEnum::A: {
            Object object( parameter );
            otherFunc( object );
        }
        break;
        
    case SomeEnum::B: {
            Object object( parameter );
            otherFunc( object );
        }
        break;
        
    case SomeEnum::C:
        anotherFunc();
        break;
    }
}

这取决于编译器和 Object。在前一个示例中,像 msvc 这样的糟糕编译器实际上将分配 less 堆栈 space,而在后一个示例中分配 N 倍多的堆栈 space。但是如果 Object 的构造函数做了一些繁重的工作 and/or 动态分配了大量内存,那么后者会更可取,因为只有达到 case 时才会调用构造函数。

也许是因为这个例子是 over-simplified,但是拥有那个对象与代码的操作几乎无关——它的值从未被使用过。因此,创建一个临时变量而不是没有任何重要用途的命名变量:

otherFunc(Object());

当然,如果otherFunc希望能够修改其参数,这将不起作用。

另一种可能性(再次假设 otherFunc 不修改其参数)是使用默认参数:

void otherFunc(Object object = Object());

现在您可以在没有显式参数的情况下调用它:

otherFunc();

并且编译后的代码将在调用点生成一个临时文件。

Can I put an initialization of this object before the switch-case statement and expect that it will be created only when it is actually being used.

没有。 C++ 标准中没有任何机制允许创建文本中所述的对象,但实际上只能 根据运行时信息创建对象。

现在,如果 Object 是微不足道的,或者如果编译器可以看到 Object 的 constructor/destructor 除了操纵该对象的状态之外没有可见的副作用,那么编译器可以根据“as-if”规则有效地将您的第一个代码转换为第二个代码。但这只是因为无法检查对象是否已创建。

请注意,“可见的副作用”包括调用内存分配函数、打开文件或其他 OS-level 重量级活动。 IE:从性能的角度来看,正是您可能特别关心的事情。因此,如果这实际上对性能很重要,那么编译器将无法“as-if”它的可能性很大。

因此,如果您明确需要延迟构建,则应在代码中明确说明。