簡體   English   中英

在現代C ++中,在函數聲明中定義返回變量是否合法?

[英]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是一個返回intint的函數。


但是,這適用於聲明。 所以這:

string r, longestDigitsPrefix(string s);

是一個有效的C ++聲明,它聲明r是一個stringlongestDigitsPrefix是一個帶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-expressionfunction-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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM