欢迎光临散文网 会员登陆 & 注册

【C/C++】string s(string())

2023-06-27 21:26 作者:冒-_-泡  | 我要投稿

标题中这句代码,是前两天在另一个视频下面提起的,如果不做提示也不做测试,大家可以先猜猜这行代码表示什么意思,例如这样写输出啥:

测试结果:

输出是“1”

从gcc的警告输出,这应该是一个坑,使得即便在没有任何“-W”选项下它也主动提醒了,警告中也回答了上面的问题:这句语句是一个“function declaration”,也就是一个函数声明,cout输出一个函数时,是转为bool值true,也就是输出1了

如果事先不知道这点,90%以上的人对这行代码的理解都会认为是一个变量定义,是通过string的临时对象来构造s这个string,但编译器显然不这么想

先来说下s为什么是一个函数,写成这样应该看得更清楚一些:

s这个函数返回string,有一个输入参数,输入参数是一个函数指针,其指向一个无参数并返回string的函数

那么为什么可以写成标题那样呢,首先,C和C++规定函数声明中,参数可以只写类型,不写参数名,例如void f(int a),可以省掉a,写成void f(int),所以上面定义中的p可以省略了:

接下来是一个相对冷的知识,首先很多人应该知道,在C和C++中,“函数”和“函数指针”是两个类型概念,它们并不等价:

但是,函数声明或定义的时候,参数类型是一个特例,和上面这个“f”不同,这个“f”虽然写在“main”函数体内,但依然是个声明,只是告知其下的代码有这么个样子的函数,“f”并不是“main”的局部变量,但是如果作为函数参数,由于参数必然是一个局部变量,所以如果其指代一个函数,则必然是函数指针,所以,参数类型如果“写作”一个函数样式,会被视为对应的指针:

这里可以看到,作为g的两个参数,虽然“f”和“pf”的写法不同,但是类型是相同的,换句话说,参数如果是函数指针,则“*”可以省略

然后我们把上面那个去掉了“p”的定义中的“(*)”也去掉,不就成了:

so,s是一个函数,就是这个原理

虽然这个例子比较极端(实践中并不会这样写),但总会有一些复杂的情况存在,特别地,在使用无参默认构造的时候,不要加括号:

不过,如果是“new”的话,写不写都可以:

因为函数类型没有size也无法构造,所以“new A()”是用无参构造一个A的新对象,而不是函数“A()”的一个新实例(没法凭空造这个函数实例)

但是从习惯上,这种时候也还是别加括号了

回到标题,如果真的需要用string的临时对象构造s这样一个string变量,警告信息中也给了推荐的办法:

给参数多加一层括号,这样编译器就会将其视为表达式“string()”,而非函数类型“string()”了

语法上将标题的s解析为函数声明,这一系列原因带有C语言的风格,实际上也正是C++语法在C基础上发展导致的,在C语言中并不会出现这种情况,因为标准C中,类型后面加圆括号只可能是表示函数类型,而且由于结构体类型强制需要“struct”关键字前缀,也不可能出现C++中的名字二义性(但是某些C扩展允许省略struct关键字,于是就有可能有问题了)

【C/C++】string s(string())的评论 (共 条)

分享到微博请遵守国家法律