C++数据类型

C++数据类型



const限定符

const是C++中一个比#define更好的规定符号常量的关键字语法。

该关键字声明的变量将只被允许初始化而不允许再被修改。

为常量命名时推荐使用全大写。

花括号初始化

可以使用花括号对数据类型进行初始化。在该语法下:

  1. 只可以使用常量进行初始化
  2. 在初始化数据超过数据类型表示范围或超出容器尺寸时,编译器将报错
  3. 。可以省略等号
  4. 对容器使用花括号初始化时,内部无元素将会为容器设置为全零
  char it{998244353};        // nope
  int arr[4]{1, 2, 3, 4, 5}; // nope
  char it{12};               // yep
  int arr[4]{1, 2, 3, 4};    // yep
  int arr[4]{};              // all zero

C风格字符串与字符串常量

C风格字符串一般指结尾为'\0'的字符数组

用双引号包裹的一般称为字符串常量,字符串常量隐式的包含'\0',因此不需要再添加'\0'。

使用字符串常量初始化字符数组时,若字符串常量长度不足字符数组长度,其余元素会全部设置为'\0'

切记只包含一个字符的字符串常量也与字符不同。除了字符串常量包含'\0'之外,字符将返回ASCLL值,而字符串常量将返回地址。

所有被空格,制表符,换行符分割的字符串常量将被自动拼接为一个字符串常量。

C风格字符串面向行的输入

cin.getline()

该方法包含两个参数,第一个是用于存储行输入的字符数组(不可使用string),第二个是即将读取的字符数量(需要包含'\0')

cin.get()

该方法与cin.getline方法类似,唯一区别是,cin.get不会读取并丢弃换行符。

但cin.get支持不指定任何参数,此时会直接读取下一个字符就像getchar一样。在使用cin.get方法时,使用无参数的cin.get方法来为下一行的读入做好准备吧

其他

cin.getline与cin.get方法在有参数时返回值都是cin对象,因此你可以在一行一句中连续调用这两个方法(注意cin.get方法在无参数时返回值是所读字符的ASCLL码)

  char charr[100];
  cin.get(charr, 20).get();
  cin.get(charr, 20);
  // or
  cin.getline(charr, 20).getline(charr, 20);

注意有很多输入都是不会读取空格,换行符之类的分割符的,在混合使用正常读入与行读入时,注意处理正常读入之后的换行符

  int num;
  (cin >> num).get(); // use get to solve '\n' behind
  string str;
  getline(cin, str);

string类行输入

getline

该函数包含两个参数,第一个指定输入流,第二个参数指定用于存储的string变量,该函数读入一行时会自动处理换行符,且不用指定字符长度。

原始字符串常量

原始字符串是一种无视任何转义的字符串,是什么字符就是什么字符。

该字符串常量使用R"(your string)"来定义,与众不同的是,原始字符串的定界符不一定需要使用"(和)",你可以在双引号与括号之间添加任意字符,来达到与string内容进行区分的目的

下例程序展示了如何通过自定义定界符输出本该被转义的内容

 cout << R"+("(Who wouldn't?"), she whispered.)+";

运行结果如下:

"(Who wouldn't?"), she whispered.

结构体

C++中使用结构体创建变量时,不再需要标明struct关键字

并且同样支持花括号初始化方法,参数位置先后顺序对应即可

C++的结构体也可以拥有成员函数,不过一般会直接用类

共用体

共用体与结构体的语法基本相同,但共用体在同一时间段只可使用其中一个成员变量

枚举类型

枚举类型的语法依然类似结构体,但其成员变量全是一些没有数据类型的名称(实际上是int类型)。

枚举类型会自动为其内部的成员变量赋一个int值,按先后顺序从0开始,每个未赋值成员变量的值是其前一个变量加一

您可以在定义枚举类型时显式的为其内部的成员变量赋值,以达到自定义赋值的效果

可以为多个成员变量赋同一个值,并且C++中可以使用long long 范围进行赋值

enum tempenum
{
    zero,
    null = 0,
    one,
    numero_uno = 1
};

枚举类型声明的变量只能在该枚举类型的成员变量里取值(即使是在枚举类型赋值范围内的int值也不可以为枚举类型声明的变量赋值),并且带有对应的int值,当进行算术运算时,该值将被自动类型转换

如果您执意要对枚举类型声明的变量进行int赋值,您当然可以使用强制类型转换,但当int值超出枚举类型有效范围时,将出现不可预测的结果

具体探究枚举类型的有效范围,该有效范围等于枚举类型内部赋值已使用的bit位的对应最大最小值

自由存储空间

new

C++中使用new 关键字来分配空间,该关键字返回一个指定数据类型的内存地址,从堆区。

typeName* pointerName = new typeName;

可以使用new来分配符合类型,比如分配一个数组的空间

int* p=new int [10];

delete

使用delete来释放指定地址的内存,但请注意delete只能用于释放new分配的内存,不可对变量地址进行释放

int num;
int* ptr=&num;
delete ptr;//nope

int* ptr2=new int;
delete ptr2;//yep

使用delete释放数组空间时,需要相应的加上方括号

int* p=new int [10];
delete [] p;

其他

new与delete的注意事项如下:

  1. 不要用delete释放不是new分配的空间
  2. 不要对同一个内存释放两次
  3. new与delete的方括号使用一定要匹配
  4. 对空指针应用delete是安全的

指针与数组

关于指针与数组名的等价关系是C语言的核心之一。

本节补充一些细枝末节的知识点

  1. 在使用sizeof时,数组名将返回数组长度,而指针会返回指针长度,哪怕两者指向的是同一地址
  2. 数组名不可进行算术运算,而指针却可以,并且有特殊的运算规则,正如c语言中的那样。
  3. 数组名与数组名地址任然存在差别,数组名是一个指向单一元素的地址,而数组名地址则是一个指向整个数组的地址。在进行指针算术时该差别非常重要

C风格字符串指针

在C语言中我们知道C风格字符串名是首字符的地址,就像数组名那样

对一个字符地址进行cout时,会将其当作C风格字符串进行处理,持续输出字符直到遇到'\0'

实际上字符串常量所传递的也是首字符地址

存储

自动存储

在函数内部定义局部变量将使用自动存储空间,一般在栈区,这种变量被称为自动变量,随着代码块活动开始而产生,随代码块活动终结而消亡

静态存储

想要变量一直存在不受代码块影响?那么使用静态存储,这种方式存储的变量可以持续的作用于全局。在所有代码块外定义或使用static关键字来修饰以进行静态存储

动态存储

上述的new和delete操作被称为动态存储,该方式使得内存的生命周期不受代码块影响,而是独立的由new和delete进行操作。

但这种操作带来了内存泄漏的风险,即使用new分配内存后,不使用delete进行释放.使得被分配的内存在整个程序活动周期内不再可用。再次提醒,new和delete一定要配套使用

vector与array

关于vector与array的使用方式详见

C++算法与数据结构Vector使用指南

在此补充两点:

  1. vecotr使用自由存储区或称堆区,而array默认使用静态存储区或称栈区
  2. vector与array拥有成员函数at,该方法访问指定下标的元素。与方括号访问的区别是,该方法会检查下标是否合法,对不合法的下标,该方法会报错。
posted @ 2025-05-22 22:56  DuckingWJ  阅读(15)  评论(0)    收藏  举报