c++構造函數參數傳遞應該是常量引用還是值?

Y616388166


本質上所有的函數參數都是傳值,是內部怎麼使用而已。比如參數是指針或引用,在參數棧中,它其實也是一個值,然後被按照指針或引用來操作——這也是數組作為參數傳遞被蛻化為指針的原因。所以,我們一般不用太在意是什麼,需要怎樣的參數就怎樣傳,編譯器會有相應的優化。

原則上說,為了效率,傳遞的參數本身尺寸應該儘量小,指針或引用、常亮都是地址值,不要以值形式傳大尺寸的結構即可,改為指針或引用形式。


TonyDeng


看你的需求,如果需要改值,傳obj&,不需要改值,最好傳 const obj&,這能省去一次構造和析構,次數多的話效率能提升不少


石頭剪子沒有布


一般來說,儘量使用常量引用的,因為引用不會再去拷貝一份參數,值傳參是要多拷貝一份的。


辰辰少兒編程


簡單變量?數組?還是指針?相關教材中一章的內容。


素食的貓


它過去通常被推薦為最佳做法。



1、到使用Const Ref的通行證所有類型,內建類型除外(, , ),用於迭代器和函數對象。(lambdas,派生自).


在…存在之前尤其如此。移動語義..原因很簡單:如果通過值傳遞,則必須創建對象的副本,並且,除了非常小的對象外,這總是比傳遞引用更昂貴。


使用C+11,我們獲得了移動語義..簡而言之,Move語義允許,在某些情況下,可以“按值”傳遞對象,而無需複製它。尤其是,當要傳遞的對象是r值.


就其本身而言,移動對象至少仍然與通過引用傳遞一樣昂貴。但是,在許多情況下,函數無論如何都會在內部複製一個對象-也就是說,它將所有權爭論的焦點。


2、在這些情況下,我們有以下(簡化)權衡:


1.我們可以通過引用傳遞對象,然後在內部複製。


2.我們可以通過值傳遞對象。


“按值傳遞”仍然會導致複製對象,除非該對象是rvalue。在rvalue的情況下,可以移動對象,因此第二個大小寫突然不再是“複製,然後移動”,而是“移動,然後(可能)再次移動”。



對於實現適當移動構造函數的大型對象(例如向量、字符串…),第二種情況是大刀闊斧比第一個更有效率。因此,建議如果函數擁有參數的所有權,並且對象類型支持高效移動,則使用PASSBY值。


事實上,任何現代編譯器都應該能夠知道什麼時候傳遞值是昂貴的,並且在可能的情況下隱式地轉換調用來使用ConstRef。


理論上。實際上,編譯器不能總是在不破壞函數的二進制接口的情況下更改它。在某些特殊情況下(當函數內聯時),如果編譯器能夠發現原始對象不會通過函數中的操作被更改,那麼副本實際上將被刪除。


但是一般來說,編譯器不能確定這一點,而C+中移動語義的出現使得這種優化變得不那麼重要了。



想要速度嗎?通過價值傳遞。


在複製成本較低的情況下,按值傳遞結構具有編譯器可能假定對象不別名(不是相同對象)的額外優勢。使用按引用傳遞的編譯器不能總是這樣認為。簡單的例子:


foo * f;void bar(foo g) { g.i = 10; f->i = 2; g.i += 5;}


編譯器可以將其優化為


g.i = 15;f->i = 2;


因為它知道f和g不具有相同的位置。如果g是一個引用(foo&),編譯器就不可能這樣認為。因為G.I可以由f->i別名,並且必須有7的值,所以編譯器必須從內存中重新獲取G.I的新值。


對於更實際的規則,下面是一組很好的規則移動構造器文章(強烈推薦閱讀)。


如果函數打算將參數更改為副作用,則以非Const引用方式進行。如果函數不修改其參數,且參數是原語類型,則按值取其值。否則由Const引用,除非在下列情況下



如果函數無論如何都需要複製Const引用,則按值取它。


上面的“原語”基本上是指一些字節長且不是多態的小數據類型(迭代器、函數對象等.)或者複製起來很昂貴。在那篇論文中,還有另一條規則。其想法是,有時一個人想要複製(如果參數不能被修改),有時一個人不想(如果一個人想要在函數中使用參數本身,如果這個參數是臨時的,例如)。論文詳細說明了如何做到這一點。在C+1x中,這種技術可以在語言支持下本地使用。在此之前,我會遵守上述規定。


示例:要使字符串大寫並返回大寫版本,就應該始終按值傳遞:無論如何,都必須獲取它的副本(不能直接更改Const引用)-因此更好地使調用方儘可能透明,並儘早將其複製,以便調用方儘可能優化-這篇文章中詳細介紹了以下內容:


my::string uppercase(my::string s) { /* change s and return it */ }


但是,如果您不需要更改參數,請參考Const:


bool all_uppercase(my::string const& s) {


/* check to see whether any character is uppercase */}


但是,如果參數的目的是將某項寫入參數,則通過非const引用傳遞它。


bool try_parse(T text, my::string &out) { /* try to parse, write result into out */}


分享到:


相關文章: