C++中使用struct S与S作为类型名的差异及不对称性解惑
C/C++中结构体类型名
struct S与S的使用差异 在C语言中,结构体<S>的完整类型名称是<struct S>;而在C++中,声明变量时既可以沿用C的写法用<struct S>作为类型名,也可以直接使用<S>,例如:
struct S {}; struct S s1; // C++中合法,兼容C写法 S s2; // C++的常规简写写法
通常大家觉得这两种写法只是个人习惯差异,但在部分场景下struct S是不被允许的,比如:
struct S1 { S1(int x = 0) : x{x} {} int x{}; }; typedef S1 S2; template<typename T> auto foo(T a) { // return struct S1{a}; // 编译报错,不合法 return S1{a}; } int main() { // foo(struct S1{1}); // 编译报错,不合法 struct S1 s2{2}; foo(s2); // struct S2 s20; // 编译报错,不合法 S2 s21; }
为什么会存在这种使用不对称?
这种差异本质是C++的语法规则划分导致的:
struct S属于类型说明符,仅适用于声明语境(比如变量、对象的声明语句);- 而表达式语境(比如创建临时对象、模板参数传递等)要求使用类型-id——也就是可以直接被表达式识别的完整类型名称,
S才是符合要求的类型-id,struct S不能作为类型-id使用。
具体场景解释:
return struct S1{a};和foo(struct S1{1});不合法:
在表达式里调用构造函数创建临时对象时,必须用类型-id来指定类型。struct关键字在这里是用于声明结构体的语法标记,属于声明语境的冗余写法,不能出现在表达式的类型引用中,因此struct S1{a}这种写法不符合语法规则。struct S2 s20;不合法:S2是typedef定义的类型别名,本身已经是完整的类型名。struct关键字只能搭配原本的结构体类型声明使用,无法和类型别名结合——编译器无法识别struct S2对应的实际类型,因此报错。
简单来说,C++保留struct S声明变量的写法只是为了兼容C代码,但这种写法的适用范围被严格限制在声明语境,不能扩展到表达式语境中。
内容的提问来源于stack exchange,提问作者wimalopaan
相关产品推荐
相关产品推荐

