[英]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.