[英]Is it legitimate in modern C++ to define a return variable in the function declaration?
我在CodeSignal上發現了一段奇怪的C ++語法:
string r, longestDigitsPrefix(string s)
{
for(auto const c : s)
{
if(isdigit(c))
r += c;
else
break;
}
return r;
}
第一行是在函數聲明之前定義string r
。 這在現代C ++中是否有效?
上面的代碼編譯並傳遞CodeSignal控制台中的所有測試,但是當我嘗試在本地編譯時它產生了編譯器錯誤( --std=c++14
)。
這是現代C ++中的有效語法嗎? 如果是這樣,它符合哪個標准修訂版?
是的,C ++語法很奇怪。 基本上,當涉及聲明 (並且只是聲明)時,我們有這樣的事情:
T D1, D2, ... ,Dn;
表示( [dcl.dcl] / 3 ):
T D1;
T D2;
...
T Dn;
這在正常情況下會很熟悉:
int a, b; // declares two ints
並且可能在您被告知擔心的情況下:
int* a, b, *c; // a and c are pointers to int, b is just an int
但是聲明者也可以引入其他東西:
int *a, b[10], (*c)[10], d(int);
這里a
是指向int的指針, b
是10個int
的數組, c
是指向10個int
的數組的指針, d
是一個返回int
的int
的函數。
但是,這僅適用於聲明。 所以這:
string r, longestDigitsPrefix(string s);
是一個有效的C ++聲明,它聲明r
是一個string
, longestDigitsPrefix
是一個帶string
並返回一個string
的函數。
但是這個:
string r, longestDigitsPrefix(string s) { return s; }
是無效的C ++。 函數定義有自己的語法,不能作為init-declarator-list的一部分出現。
該函數的定義也很糟糕,因為它使用全局變量來跟蹤狀態。 因此,即使它是有效的, longestDigitsPrefix("12c")
將第一次返回"12"
,但第二次返回"1212"
......
通過閱讀ISO C ++ 14草案N4140附件A [gram],我很確定它是不正確的,因為我無法找到從翻譯單元中推斷出語法的方法。
translation-unit - > declaration-seq - > declaration - > block-declaration | 功能定義| 連桿規格| ...
function-definition:attribute-specifier-seqopt decl-specifier-seqopt declarator virt-specifier-seqopt function-body
聲明符:ptr-declarator noptr-declarator參數和限定符trailing-return-type
但你的行更多是逗號運算符,但它的語法是:
表達式:賦值表達式 表達式,賦值表達式
assignment-expression:conditional-expression | 邏輯或表達| 賦值運算符| initializer-clause | 扔表達
從assignment-expression
到function-definition
是沒有辦法的
更新:感謝Barry,嘗試解析你的文本的另一種方法是嘗試從init-declarator-list
(你可以從block-declaration
獲得)到function-definition
:
init-declarator-list:init-declarator | init-declarator-list,init-declarator
init-declarator:declarator initializeropt
和
聲明符:ptr-declarator noptr-declarator參數和限定符trailing-return-type
會允許你進行函數聲明而不是定義。 所以這個奇怪的代碼是合法的:
#include <string>
using std::string;
string r, longestDigitsPrefix(string s);
string longestDigitsPrefix(string s) {
for(auto const c : s)
{
if(isdigit(c))
r += c;
else
break;
}
return r;
}
int main(int argc, char *argv[]) {
longestDigitsPrefix("foo");
return 0;
}
但是我可能是錯的,因為我不習慣使用C ++的形式語法,這是正常的,因為它的語法非常復雜,並且有一些非平凡的行為。
據我所知,這不是一個有效的函數聲明。
函數中的前綴只能用作定義函數的“返回”變量的類型,而不是變量本身。
但是,您可以在函數外部聲明一個變量(從而使其成為全局變量)並在函數內部修改它,就像您可能嘗試過的那樣,但是您需要將所述變量作為函數參數中的引用傳遞。 您還需要將函數設置為void,因為它不會返回變量,而只是修改它
例
std::string foo = "Hello";
void foo_func(std::string &string)
{ //do something with the string
}
//call the function and modify the global "foo" string
foo_func(foo);
如果您將此作為優化,那么只要返回一個變量,那么大多數編譯器將在調用者的堆棧上分配返回變量,而不是被調用者。
您所要做的就是在被調用者的上下文中聲明變量,並確保有1個返回點,或者所有返回點都返回相同的變量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.