除复制省略外,还有没有其他机制可以优化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;
    }
}

解决方法

我可以在switch-case语句之前放置此对象的初始化,并希望仅在实际使用该对象时创建该对象。

不。 C ++标准中没有机制允许根据运行时信息仅实际上创建要创建在文本中声明的对象。

现在,如果Object不重要,或者如果编译器可以看到Object的构造函数/析构函数在处理该对象的状态之外没有可见的副作用,那么编译器可以“假设”规则可将您的第一个代码有效地转换为第二个代码。但这仅仅是因为没有人可以检查对象是否已创建。

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

因此,如果您有明确的需要来延迟构建,则应该在代码中对其进行明确的说明。

,

这取决于编译器和Object。在前一个示例中,一个错误的编译器(如msvc)实际上将分配 less 堆栈空间,而在后者中,N倍于此。但是,如果Object的构造函数做了一些繁重的工作和/或动态分配了大量内存,则后者是可取的,因为只有到达 case时才会调用该构造函数。>

,

也许是因为此示例过于简化,但是拥有该对象与代码的操作几乎无关紧要-从未使用过它的值。因此,创建一个临时变量来代替没有太大用的命名变量:

otherFunc(Object());

当然,如果otherFunc希望能够修改其参数,则此方法将无效。

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

void otherFunc(Object object = Object());

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

otherFunc();

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