[C++] 使用'const'作為函數參數


Answers

“當參數按值傳遞時,const是毫無意義的,因為你不會修改調用者的對象。”

錯誤。

這是關於自我記錄你的代碼和你的假設。

如果你的代碼有很多人在使用它,而你的函數並不重要,那麼你應該標記“const”。 在編寫行業代碼時,你應該始終假定你的同事是精神病患者,試圖盡可能地讓你得到你(特別是因為它往往是你自己的未來)。

此外,正如前面提到的那樣,它可能會幫助編譯器優化一些東西(儘管這是一個很長的過程)。

Question

你用const去多遠? 你是否只是在必要時使函數成為const ,或者你是否全力以赴地使用它? 例如,設想一個簡單的帶有單個布爾參數的增變器:

void SetValue(const bool b) { my_val_ = b; }

那個const實際上有用嗎? 我個人選擇廣泛使用它,包括參數,但在這種情況下,我想知道它是否值得?

我也驚訝地發現,你可以在函數聲明中忽略const的參數,但可以將它包含在函數定義中,例如:

.h文件

void func(int n, long l);

.cpp文件

void func(const int n, const long l)

是否有一個原因? 這對我來說似乎有點不尋常。




標記值參數'const'絕對是一種主觀的東西。

不過,我實際上更喜歡標記值參數const,就像在你的例子中一樣。

void func(const int n, const long l) { /* ... */ }

我的價值在於清楚地表明函數永遠不會改變函數參數值。 它們在開始和結束時會有相同的價值。 對我而言,這是保持一種非常實用的編程風格的一部分。

對於一個簡短的函數來說,在'const'那裡可以浪費時間/空間,因為通常很明顯參數不會被函數修改。

然而對於一個更大的函數,它是一種實現文檔的形式,並且由編譯器執行。

我可以肯定,如果我用'n'和'l'做一些計算,我可以重構/移動這個計算,而不用擔心會得到不同的結果,因為我錯過了一個或兩個變化的地方。

由於它是一個實現細節,因此不需要在頭中聲明值參數const,就像不需要聲明與實現使用的名稱相同的函數參數一樣。




我不會把常量放在這樣的參數上 - 每個人都已經知道一個布爾值(而不是布爾值)是常量,因此添加它會讓人們想“等等,什麼?” 甚至你通過引用傳遞參數。




我不使用const作為值傳遞參數。 調用者不關心你是否修改參數,它是一個實現細節。

真正重要的是,如果方法不修改它們的實例,則將方法標記為常量。 這樣做,因為否則,你可能會得到很多const_cast <>或者你可能會發現標記一個方法const需要改變很多代碼,因為它調用了其他應該標記為const的方法。

如果我不需要修改它們,我也傾向於標記局部變量const。 我相信通過使代碼更易於識別“移動部分”,使代碼更易於理解。




const應該是C ++中的默認值。 喜歡這個 :

int i = 5 ; // i is a constant

var int i = 5 ; // i is a real variable



我可以使用const。 參數Const表示它們不應該改變它們的值。 通過參考傳遞時這特別有價值。 const函數聲明該函數不應該改變類成員。




There's really no reason to make a value-parameter "const" as the function can only modify a copy of the variable anyway.

The reason to use "const" is if you're passing something bigger (eg a struct with lots of members) by reference, in which case it ensures that the function can't modify it; or rather, the compiler will complain if you try to modify it in the conventional way. It prevents it from being accidentally modified.




All the consts in your examples have no purpose. C++ is pass-by-value by default, so the function gets copies of those ints and booleans. Even if the function does modify them, the caller's copy is not affected.

So I'd avoid extra consts because

  • They're redudant
  • They clutter up the text
  • They prevent me from changing the passed in value in cases where it might be useful or efficient.






Const參數只有在參數傳遞時才有用,例如引用或指針。 當編譯器看到一個const參數時,它確保參數中使用的變量在函數體內不被修改。 為什麼會有人想讓按值參數保持不變? :-)




在這篇關於comp.lang.c ++的舊文章“Guru of the Week”中有關於這個主題的很好的討論。

相應的GOTW文章可在Herb Sutter的網站上here




Being a VB.NET programmer that needs to use a C++ program with 50+ exposed functions, and a .h file that sporadically uses the const qualifier, it is difficult to know when to access a variable using ByRef or ByVal.

Of course the program tells you by generating an exception error on the line where you made the mistake, but then you need to guess which of the 2-10 parameters is wrong.

So now I have the distasteful task of trying to convince a developer that they should really define their variables (in the .h file) in a manner that allows an automated method of creating all of the VB.NET function definitions easily. They will then smugly say, "read the ... documentation."

I have written an awk script that parses a .h file, and creates all of the Declare Function commands, but without an indicator as to which variables are R/O vs R/W, it only does half the job.

編輯:

At the encouragement of another user I am adding the following;

Here is an example of a (IMO) poorly formed .h entry;

typedef int (EE_STDCALL *Do_SomethingPtr)( int smfID, const char* cursor_name, const char* sql );

The resultant VB from my script;

    Declare Function Do_Something Lib "SomeOther.DLL" (ByRef smfID As Integer, ByVal cursor_name As String, ByVal sql As String) As Integer

Note the missing "const" on the first parameter. Without it, a program (or another developer) has no Idea the 1st parameter should be passed "ByVal." By adding the "const" it makes the .h file self documenting so that developers using other languages can easily write working code.




如果你使用->*.*運算符,這是必須的。

它阻止你寫類似的東西

void foo(Bar *p) { if (++p->*member > 0) { ... } }

我現在差不多做了,而且這可能不符合你的意圖。

我想說的是

void foo(Bar *p) { if (++(p->*member) > 0) { ... } }

如果我在Bar *p之間放置了一個const ,編譯器會告訴我這一點。




以下兩行在功能上是等同的:

int foo (int a);
int foo (const int a);

顯然,如果它是以第二種方式定義的,你將無法修改foo的主體,但與外部沒有區別。

const真正派上用場的地方是使用引用或指針參數:

int foo (const BigStruct &a);
int foo (const BigStruct *a);

這說的是,foo可以接受一個大參數,也許是一個千兆字節大小的數據結構,而不需要復制它。 另外,它對調用者說,“Foo不會*改變該參數的內容。” 傳遞const引用也允許編譯器做出某些性能決定。

*:除非它消除了常量,但這是另一篇文章。




啊,一個艱難的。 一方面,聲明是一個契約,它根據值傳遞一個const參數是沒有意義的。 另一方面,如果你看看函數的實現,如果你聲明了一個參數常量,那麼你給編譯器更多的機會來優化。