结构体与对象聚合
结构体:对基本数据结构进行扩展,将多个对象放置在一起视为一个整体
– 结构体的声明与定义(注意定义后面要跟分号来表示结束)
– 仅有声明的结构体是不完全类型( incomplete type )
struct Str1;
struct Str
{
int x;
int y;
}; //用分号来表示结束
int main()
{
Str m_str;
m_str.x = 3;
std::cout << m_str.x << std::endl;
Str1 m_str1; //Error: Variable has incomplete type 'Str1'
Str1 *m_str1P; //OK
return 0;
}
– 结构体(以及类)的一处定义原则:翻译单元级别
即如果source.cpp中使用到了结构体Str,就要在source.cpp中包含一次(只能包含一次)
//source.cpp
struct Str
{
int x;
int y;
};
void fun()
{
Str m_str;
return 0;
}
如果main.cpp中使用到了结构体Str,就要在main.cpp中包含一次(只能包含一次)
//main.cpp
struct Str
{
int x;
int y;
};
void fun();
int main()
{
Str m_str;
fun();
return 0;
}
数据成员(数据域)的声明与初始化
struct Str //1
{ //2
int x; //数据声明 //3
int y; //数据声明 //4 整个的1、2、3、4、5行称为结构体的定义
}; //5 结构体内包含的数据成员称为数据成员的声明
int x; //数据的定义
extern int y; //数据的声明
int main()
{
Str m_str; //结构体对象的定义,隐式地定义了x和y
//即: 程序运行到该处,系统为它分配相应的内存,用户可以通过使用变量来访问相应的内存
return 0;
}
– ( C++11 )数据成员可以使用 decltype 来声明其类型,但不能使用 auto
struct Str
{
decltype(3) x; //OK since C++11
decltype(3) x2 = 3; //OK
auto x3 = 3; //Not allowed
int y;
};
– 数据成员声明时可以引入 const 、引用等限定
struct Str
{
const int x = 3; //OK
int y;
};
– 数据成员会在构造类对象时定义
struct Str
{
const int x =3;
int y;
};
int main()
{
Str m_str; //数据成员在构造类对象时时定义
return 0;
}
– ( C++11 )类内成员初始化
struct Str
{
int x =3;
int y;
};
int main()
{
Str m_str;
std::cout<< m_str.x << '\n';
return 0;
}
– 聚合初始化:从初始化列表到指派初始化器
struct Str
{
int x;
int y;
};
int main()
{
Str m_str{3,4}; //初始化列表,未指定值时用0填充
std::cout<< m_str.x << '\t' << m_str.y << '\n';
Str m_str2{3}; //初始化列表
std::cout<< m_str2.x << '\t' << m_str2.y << '\n';
Str m_str3{}; //初始化列表
std::cout<< m_str3.x << '\t' << m_str3.y << '\n';
return 0;
}
struct Str
{
int x;
int y;
};
struct Str2
{
int y;
int x;
};
int main()
{
Str m_str{3,4}; //初始化列表
std::cout<< m_str.x << '\t' << m_str.y << '\n';
Str2 m_str2{3,4}; //初始化列表
std::cout<< m_str2.x << '\t' << m_str2.y << '\n';
//初始化列表的元素顺序与结构内数据声明顺序一致
return 0;
}
struct Str
{
int x;
int y;
};
struct Str2
{
int y;
int x;
};
int main()
{
Str m_str{.x=3, .y= 4}; //指派初始化器, since C++20
std::cout<< m_str.x << '\t' << m_str.y << '\n';
Str2 m_str2{.y= 4, .x=3}; //指派初始化器, since C++20
std::cout<< m_str2.x << '\t' << m_str2.y << '\n';
return 0;
}
mutable 限定符
struct Str
{
mutable int x = 0; //mutable只能修饰结构体内的数据成员
int y = 1;
};
int main()
{
const Str m_str;
std::cout<< m_str.x << '\t' << m_str.y << '\n';
m_str.x = 3; //可以修改一个const Str类型的对象的有mutable修饰的数据成员
std::cout<< m_str.x << '\t' << m_str.y << '\n';
return 0;
}
参考资料
深蓝学院:C++基础与深度解析