C++复合变量类型(第二弹)

19 阅读7分钟

书接上文

C++基础变量类型(第一弹)

简单了解一下C++有哪一些复合类型

C++复合类型由数组,字符串,结构,共用体,枚举,指针组成,学习了复合类型之后,需要了解如何通过new和delete管理动态内存,这是C++的精髓之一。

数组

数组(Array)是一种数据格式,能够存储多个同类型的值;

数组声明和使用

C++数组跟大多数语言一样,都是从0开始的,而且定义的时候也是通过“[]”定义数组长度或者通过“{}”对数组进行初始化,使用sizeof(array)填入数组名称时,打印出的是数组中所占用的内存大小。 代码:

using namespace std;
#include <iostream>
#include <climits>
// 数组声明
int yams[100];
int main()
{
    // 数组使用
    yams[0] = 1;
    yams[1] = 2;
    cout << yams[0] << endl;
    cout << yams[1] << endl;

    // 数组声明
    int arrays[]{3,4,5};
    cout << arrays[0] << endl;
    cout << arrays[1] << endl;

    cout<<"数组总字节长度是: "<<sizeof(arrays)<<endl;
    return 0;
}

输出结果:

image.png 每个int占用4个字节,所以sizeof输出的是3*int = 12字节。

C++数组初始化的一些规则

C++数组初始化时,例如 int array [4]={1},则默认array[0] = 1,其他则是初始化为0,初始化的数目是不能超过数组定义的长度的。 C++11数组初始化时,可以省略等号,例如:int array[4]{1,2,3,4}。 数组初始化时,禁止缩窄操作,例如:int array[4]{1,1.0,3.14}中3.14为浮点类型转换为整数是一种缩窄的操作。

字符串

字符串是存在在连续内存中的一系列字符,C++处理字符串的方式有两种,第一种是来自于C语言的,第二种是来自于C++标准库的string。

C语言的字符串

C语言的字符串有一个特殊的性质,就是字符串末尾是以空字符结尾"\0";这个特性对C语言的字符串来说至关重要,许多函数包括C++对字符串的处理(兼容C语言)都会处理达到空字符串为止。主要学习C++所以C类型字符串了解一下就行。

定义C语言的字符串

代码:

using namespace std;
#include <iostream>
int main()
{
    char h[] = "hello world";
    cout << h << endl;
    cout << sizeof h << endl; // 输出12
}

有同学好奇,“hello world”一共加上空格也就11个字符,怎么会输出12个呢?原因是因为“\0”空字符也占用了一个字符。

C++语言的字符串

C++98标准通过添加string类扩展了C++标准库,通过面向对象的方式去使用string对象,隐藏了字符串实现的细节。

C++字符串定义和使用

C++字符串定义能够类似定义基础变量的形式进行定义,例如string str = "a",通过“+”号进行两个字符串的拼接。 代码:

using namespace std;
#include <iostream>

int main()
{
    // 字符串定义
    string s1 = "Hello";
    string s2 = "World";
    // 拼接字符串
    string s3 = s1 + s2;
    cout << s3 << endl;
    cout << s3 + "a" << endl;
}

输出结果; image.png

C++字符串的Api----后续去官网补充

结构体

结构是用户自定义的类型,结构体定义了这种类型之后,就能够通过结构体定义变量。

结构体的定义与使用

结构体定义后,可以直接通过变量定义的方式进行初始化,后续通过“.”访问成员属性。

using namespace std;
#include <iostream>
struct student
{
    string name;
    int age;
};
int main()
{
    // 定义结构体
    student st{
        "小智",
        18
    };

    // 使用结构体
    cout << "我的名字是:" + st.name<<"  今年 " + std::to_string(st.age) + "岁" << endl;
}

输出结果:

image.png

结构体声明的位置

结构体声明的位置是比较重要的,在函数内声明只能在函数内使用,函数外声明可能所有函数都共用。

using namespace std;
#include <iostream>
// 函数外声明,任何人都可以使用
struct student
{
    string name;
    int age;
};
int main()
{
    // 函数内声明,只有函数内可用
    struct teacher
    {
        string name;
        int age;
    };
}

结构体的其他属性

C++的结构体与内置类型基本相似,可以作为函数的参数传递,也可以作为函数返回值进行返回,也可以通过“=”号对相同的类型的结构体进行赋值。

匿名结构体

匿名结构体是指声明一个没有名字的结构体,后续通过结构变量名进行访问,注意下面代码的“teacher”不是结构体名,而是变量名;这样声明的结构体,后续无法服用,不太建议用这种方法声明结构体。

using namespace std;
#include <iostream>
int main()
{
    // 匿名结构体
    struct
    {
        string name;
        int age{};
    }teacher;
    teacher.name = "Teacher";
    teacher.age = 18;
    cout<<"Name: "<<teacher.name<<endl;
    cout<<"Age: "<<teacher.age<<endl;
}

结构体数组

既然基础变量可以声明为数组,那结构体也是可以的,初始化方法与基础变量类似。

using namespace std;
#include <iostream>
// 函数外声明,任何人都可以使用
struct student
{
    string name;
    int age;
};
int main()
{
    student stuArray[2]{
        {
            "小智", 18
        },{
            "小雅",17
        }};
    for(int i=0;i<2;i++)
    {
        cout<<"我的名字是: "+stuArray[i].name<<endl;
        cout<<"今年: "<<to_string(stuArray[i].age)+"岁"<<endl;
    }
}

代码输出:

image.png

结构体的位字段

C++允许指定占用特定位数的结构体成员,字段类型必须是枚举和整形,通过“:”指定使用的位数;如下代码所示,age为8位占用1字节,范围是-128-127,所以小智年龄是“正常”(127岁也不正常- -!)的,小雅的是溢出的。 代码:

using namespace std;
#include <iostream>
// 函数外声明,任何人都可以使用
struct student
{
    string name;
    int age:8;
};
int main()
{
    student stuArray[2]{
        {
            // 正常
            "小智", 127
        },{
            // 溢出
            "小雅",128
        }};
    for(int i=0;i<2;i++)
    {
        cout<<"我的名字是: "+stuArray[i].name<<endl;
        cout<<"今年: "<<to_string(stuArray[i].age)+"岁"<<endl;
    }
}

输出结果: image.png

共用体

共用体是一种数据格式,它能够存储不同的数据类型,但同时!同时!同时!只能存储1种。

共用体的定义和使用

共用体的定义方式和结构体类似,但定义的成员是共用一片内存的,当一个成员赋值时,会覆盖掉前一个成员的数值;下面代码是由两个int,一个double组成的,第一次给year赋值时,由于year和month都是int,共用内存所以输出的是同样的值,但是day就奇奇怪怪了;相反给day赋值,year和month看起来也是奇奇怪怪,不能工作;共用体通常用于节省内存,在嵌入式编程中比较常用,游戏服务器嘛...emmmm,当然自己能熟练使用也不错。 代码:

using namespace std;
#include <iostream>
// 函数外声明,任何人都可以使用
union date
{
    int year;
    int month;
    double day;
};
int main()
{
    date d1;
    d1.year = 12;
    cout <<"year: "<< d1.year << endl;
    cout <<"month: "<< d1.month << endl;
    cout <<"day: "<< d1.day << endl;
    d1.month = 28;
    cout <<"year: "<< d1.year << endl;
    cout <<"month: "<< d1.month << endl;
    cout <<"day: "<< d1.day << endl;
    d1.day = 3.14;
    cout <<"year: "<< d1.year << endl;
    cout <<"month: "<< d1.month << endl;
    cout <<"day: "<< d1.day << endl;

}

输出结果:

image.png

枚举

什么是枚举,有过编程经验的小伙伴自然是知道了,枚举就是一个可以有穷列举出来的常量咯,比如颜色{红,橙,黄}。

C++枚举定义和使用

C++定义枚举也跟结构体类似,只不过不需要填写类型,而是直接填写枚举参数名;正常情况下,枚举初始值从0开始,后续紧跟着初始值+1; 代码:

using namespace std;
#include <iostream>
enum color { red, green, blue };
int main()
{
    color r = red;
    color g = green;
    color b = blue;

    cout << r << endl;
    cout << g << endl;
    cout << b << endl;

}

代码输出:

image.png

枚举使用注意事项

枚举只是实现了“=”赋值运算符的重载,也就是说枚举之间不能使用+号进行赋值,但枚举会转换成int类型进行符号运算,运算后的值也是int类型;同理不能将int类型转换为枚举类型。

代码:

using namespace std;
#include <iostream>
enum color { red, green, blue };
int main()
{
    color r = red;
    color g = green;
    color b = blue;

    // color c = 1 + red; // 非法,编译报错
    // color c1 = 1; // 非法报错
    int a = red + green + blue; // 合法,输出3
    cout<<a<<endl;
}

输出结果:

image.png

枚举设置值

枚举是可以设置值的,默认情况下从0开始递增,如果遇到设置的值,则从设置的值开始递增;例如{red, green = 1001, blue} red为0,green为1001,blue为1002;

using namespace std;
#include <iostream>
enum color { red, green= 1001, blue };
int main()
{
    color r = red;
    color g = green;
    color b = blue;

    cout << r << " " << g << " " << b << endl;
}

输出结果:

image.png