是否有可能确保复制省略?

时间:2011-05-26 14:42:18

标签: c++ diagnostics compiler-directives copy-elision

Copy elision是一种简洁的优化技术,在某些情况下依赖于复制省略can actually be faster,而不是“手动”传递引用。

因此,我们假设您已经确定了一个关键代码路径,您依赖于编译器为代码路径执行复制省略以获得最佳性能。

但现在你依赖于编译器优化。

是否有任何(编译器特定的,显然)方式确保实际执行复制省略并且如果无法执行复制省略,编译器(或其他工具)会生成警告/错误?

(我正在考虑与Visual C ++的__forceinline远程类似的东西,如果编译器没有内联标记的函数,则会产生警告。)

3 个答案:

答案 0 :(得分:4)

没有

但你可以编写一个等效的,但完全不可读的代码:

BigObj f()
{
    BigObj x(g());
    x.someMethod();
    return x;
}

//...
BigObj z = f();
//...

被翻译(带有副本省略):

void f(BigObj* obj)
{
    new(obj) BigObj(g());
    obj->someMethod();
}

//...
char z[sizeof(BigObj)];
f((BigObj*)&z[0]);
//...
((BigObj*)&z[0])->~BigObj();

但严重的是,只需编写代码,编译器就可以忽略副本。即只返回一个没有分支的对象:

BigObj f()
{
    BigObj x, y;
    // use x and y
    if(condition)
        return x;
    else
        return y;
    // cannot be elided
}


BigObj f()
{
    if(condition)
    {
        BigObj x;
        return x;
    }
    else
    {
        BigObj y;
        return y;
    }
    // can be elided
}

答案 1 :(得分:4)

不是这样,除了在复制构造函数中放置assert(false);

否则,请使用您最喜爱的探查器来衡量应用程序中有趣的部分是否足够快。

答案 2 :(得分:2)

在C ++ 1z(预计2017年)中,需要一些案例来保证复制省略:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html

根据communal cppreference.com compiler feature support wiki GCC 7+和Clang 4+确保这一点。

幸运的是,优化方面不应该要求启用更新的语言支持,因为它是纯粹的优化(遵循较旧的语言标准限制)。

同样允许复制构造函数在优化应用时不可用,可能需要在编译期间启用较新的语言标准,或者使用不要求严格一致性的松散或扩展模式(例如,可能是GCC&# 39; s -fpermissive)。