C ++:按值返回,与持久对象的引用返回?

时间:2013-07-26 14:14:42

标签: c++ optimization return return-by-reference return-by-value

编译器优化后的程序速度哪个更好:按值返回,或者通过引用返回到持久对象?

/// Generate a 'foo' value directly as a return type.
template< typename T >
inline T gen_foo();

/// Get a 'foo' reference of a persistent object.
template< typename T >
inline T const& get_foo();

T将是基元,指针,成员指针或用户定义的小型P.O,D。类数据。

据我所知,它是按值传递的,但是有可能通过引用传递:

  • 通过按值:

    • 返回一个T是一个较小的对象,可以快速复制到调用者的变量中。
    • 优化器可以使用(N)RVO和copy-elision删除返回副本。
    • 优化器可以将生成代码或生成的值内联到调用者的代码中。
    • 程序不需要访问RAM,也不需要缓存。
  • 通过按引用:

    • 优化器可能会完全评估持久值,并将其用法替换为文字等效值。是否发生这种情况会影响分析的其余部分。
    • 如果持久值被完全评估并替换为文字:
      • 没有值返回。
      • 优化器可以轻松地内联文字。
      • 程序不需要访问RAM,也不需要缓存。
    • 如果持久值无法完全评估和替换:
      • 返回一个引用是一个小对象,并快速复制到调用者的变量。
      • 优化器可以使用(N)RVO和copy-elision来避免返回副本。
      • 优化器无法将生成代码或生成的值内联到调用者的代码中。
      • 程序需要访问RAM,尽管这可能在L1 / L2 /等中。高速缓存中。

背景

我被迫考虑这个因为在某些平台上,如果我按值返回会触发一些浮点异常,但如果我按参数填充引用则不会。 (这是给定的;这个问题不是要讨论这一点。)因此,我想要的API,以及我不得不考虑使用的API是:

/// Generate a 'foo' value directly as a return type.
template< typename T >
inline T gen_foo();

/// Fill in a 'foo' passed in by reference.
template< typename T >
inline void fill_foo( T& r_foo );

因为,我厌恶'填充'API,(因为它将定义与初始化分开,阻止创建临时值等),我可以将其转换为引用返回版本,例如:

/// Forward-declare 'Initialized_Foo'.
template< typename T > struct Initialized_Foo;

/// Get a 'foo' reference; this returns a persistent reference to a static object.
template< typename T >
inline T const& get_foo()
{
    #if 0
    // BAD: This calls 'fill_foo' *every* time, and breaks const-correctness.
    thread_local static const T foo;
    fill_foo( const_cast< T& >( foo ) );
    return foo;
    #else
    // GOOD: This calls 'fill_foo' only *once*, and honours const-correctness.
    thread_local static const Initialized_Foo< T > initialized_foo;
    return initialized_foo.data;
    #endif
}

/// A 'foo' initializer to call 'fill_foo' at construction time.
template< typename T >
struct Initialized_Foo
{
    T data;
    Initialized_Foo()
    {
        fill_foo( data );
    }
};

0 个答案:

没有答案