繁体   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