![](/img/trans.png)
[英]Will the c++ compiler optimize away unused return value by `reference`?
[英]Will a good C++ compiler optimize a reference away?
我想寫一個模板函數,它的東西用std::stack<T>
和實例T
,如:
template<class StackType> inline
bool some_func( StackType const &s, typename StackType::value_type const &v ) {
// ...
}
我通過引用傳遞v
的原因當然是針對StackType::value_type
是struct
或class
而不是按值復制整個對象的情況進行優化。
但是,如果StackType::value_type
是像int
這樣的“簡單”類型,那么當然更好的方法就是按值傳遞它。
問題是:對於像int
這樣的類型,它將成為int const&
作為上述函數中的形式參數,編譯器是否會優化掉引用並簡單地按值傳遞它?
我在這里查看gcc優化選項http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
實際上,您的案例有一個選項:
-fipa-SRA
執行過程的標量替換聚合,刪除未使用的參數以及通過值傳遞的參數替換參考傳遞的參數。
在-O2,-O3和-Os級別啟用
據我所知,-O2是Linux上發布版本的常用選項。
所以,簡短的回答是: 好的編譯器之一
雖然我實際上沒有為此測試任何編譯器,但我對此表示懷疑。 您假設傳遞const引用與僅傳遞值無法區分,但這不是真的,並且編譯器不應該假設它是。
由於引用是const,因此您的函數不能通過它修改值,但代碼的其他部分可能可以訪問原始(非const)變量,並可能修改它。 例如,您的函數可能會調用其他一些更改它的函數,或者可能有另一個並發運行的函數。
如果其他內容修改了原始變量,則您的函數及其引用應該會看到新值。 如果編譯器用副本替換了引用,則該函數仍將看到舊值。
不過,您可能對Boost的呼叫特征庫感興趣。 它提供了一個模板類型call_traits<T>::param_type
,它是您不想復制的“大”類型的const引用,以及“小”類型的值,其中副本效率更高。 基本上,您希望編譯器隱式執行的操作,您可以使用您的代碼進行顯式操作。
每當編譯器能夠內聯時,產生的跨程序優化將消除查找和傳遞地址的費用。
對於非內聯函數調用,引用可能將實現為指針,而不是按值傳遞。
這是MSVC2010 64位編譯器,完全優化:
int foo( int i )
{
int a = i + i;
return ( a );
}
//Disassembly:
//00000001`3ff11c50 8d0409 lea eax,[rcx+rcx]
//00000001`3ff11c53 c3 ret
int bar( int const & i )
{
int a = i + i;
return ( a );
}
//Disassembly:
//00000001`3ff11c10 8b01 mov eax,dword ptr [rcx]
//00000001`3ff11c12 03c0 add eax,eax
//00000001`3ff11c14 c3 ret
在第一種情況下,值被傳遞RCX
,在第二-傳遞地址RCX
。 當然,如果函數是內聯的,正如Ben所說,那么在兩種情況下生成的代碼都可能完全相同。
傳遞“小”類的實例(比如,類只有一個int
數據成員和普通構造函數,按位復制構造函數等)的值更快。 編譯器將優化它,基本上只是傳遞int
的副本。 因此,正如Wyzard指出的那樣,你可以使用某些類型特征來重載你的函數。 像這樣的東西:
template< typename PType >
PType Func( typename std::enable_if< ( sizeof( PType ) > sizeof( size_t ) ), PType const & >::type f )
{
//large things: reference
}
template< typename PType >
PType Func( typename std::enable_if< ( sizeof( PType ) <= sizeof( size_t ) ), PType >::type f )
{
//small things: value
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.