C++基础入门
1.c++初始化
在我们学习c语言的时候初始化都是
int a=10;
int ar[10]={1,2,3,4,5,6,7,8,9,10};
struct Student
{char s_id[20];char s_name[20];char s_sex[20];char s_age[20];
};
struct Student s1={"2024001","zl","man",12 };
c++中我们通常用{}进行初始化
int b(10);
int c{ 10 };//对所有的方式进行初始化
int d = int(10);
int e = int{ 10 };
int ar[10] = { 1,2,3,4,5,6 };//未初始化是的后面是0// 0 1 2 3 4 5 6 7 8 9
int br[10]{ 1,2,3,4,5,6 };
struct Student
{char s_id[20];char s_name[20];char s_sex[20];char s_age[20];
};
struct Student s1{"2024001","zl","man",12 };
int* p{ NULL };
NULL和nullptr的区别?
| 特性 | NULL | nullptr |
|---|---|---|
| 本质 | 宏定义(通常是整数 0 或 (void*) 0) | C++11+ 关键字(专门的空指针标识) |
| 类型 | 无独立类型(int 或 void*) | std::nullptr_t(独立类型) |
| 类型安全 | 弱(可转整数 / 指针,易歧义) | 强(仅可转指针,不可转整数) |
| 函数重载歧义 | 有(可能匹配整数版本) | 无(仅匹配指针版本) |
| 语义清晰度 | 低(本质是 0,需人工联想空指针) | 高(直接表示空指针,无歧义) |
| 适用标准 | C++ 所有版本、C 语言 | C++11 及以上 |
| 模板编程适配 | 差(推导类型可能错误) | 好(类型明确,推导准确) |
2.输入输出
int main()
{const int Strlen = 32;char stra[Strlen] = {};char strb[Strlen] {};//scanf("%s", stra);//' '\n//scanf_s("%s", stra, sizeof(stra));//两个区别//fgets(stra, Strlen, stdin);//\ncin >> stra;cout << stra;cin.getline(stra, Strlen);//31 \0 \n字符串的结束cin.getline(stra, Strlen, '#');//以#作为字符串结束的标志
}
int main()
{int a = 0;char ch = '\0';cin >> a >> ch;cout << a <<" " << ch <<endl;return 0;
}
3.const关键字
1.const在C语言和c++中的区别?
const int LEN = 10;
int ar[LEN]; //错误 c++可以在C语言中,const是以变量为主,定义时必须对其初始化
2.指针与const的两种结合方式
const在*左侧:修饰指针指向的内容(内容不可被修改)
int a = 10;
const int* p = &a; // const 在*左侧,限制“指向的内容”// 验证规则:
p = &b; // 合法!指针本身可改(可以换指向的地址)
*p = 20; // 编译错误!指向的内容不可改(不能通过指针改a的值)
const在*右侧:修饰指针变量本身(指针指向不可修改)
int a = 10;
int* const p = &a; // const 在*右侧,限制“指针本身”,必须初始化// 验证规则:
*p = 20; // 合法!指向的内容可改(a的值会变成20)
p = &b; // 编译错误!指针本身不可改(不能换指向其他地址)
结合讲解:
int main() {const int a = 10; // 常变量a,值不可改// 1. int *p1 = &a; // 错误(error):p1是“普通int变量”,&a是“const int*指针”,类型不匹配,不能把指针赋值给普通变量。// 2. const int *p2 = &a;// 合法(ok):p2是“指向常变量的指针”(const在*左侧,限制内容),可以指向常变量a(符合“保护常变量”的规则)。// 3. int *const p3 = &a;// 错误(error):p3是“指针常量”(const在*右侧,限制指针本身),但它是“普通指针(无const内容限制)”,不能指向常变量a(否则可能通过p3修改a的值,违反常变量定义)。// 4. const int *const p4 = &a;// 合法(ok):p4是“指向常变量的指针常量”(*左右都有const),既限制指针指向,又限制内容修改,可安全指向常变量a。// 5. int *p5 = (int*)&a;// 编译能过(ok),但不安全:通过“强制类型转换”把“const int*”转成“int*”,绕过了编译器的类型检查。// 风险:后续若通过p5修改*p5,会直接修改常变量a的值,违反const语义(C++标准未定义这种行为,可能导致程序崩溃)。
int main() {int a = 10, b = 20;int *p = &a; // 普通指针p(无任何const限制)// 1. int *s1 = p;// 合法(ok):s1和p都是“普通指针”,类型完全一致,直接赋值。// 2. const int *s2 = p;// 合法(ok):s2是“指向常变量的指针”(能力比p收缩:p能改内容,s2不能改),符合“能力强→能力收缩”的规则。// 本质:给指针“加限制”(从“能改内容”变成“不能改”),是安全的。// 3. int *const s3 = p;// 合法(ok):s3是“指针常量”(能力比p收缩:p能改指向,s3不能改),符合“能力强→能力收缩”的规则。// 本质:给指针“加限制”(从“能改指向”变成“不能改”),是安全的。// 4. const int *const s4 = p;// 合法(ok):s4是“指向常变量的指针常量”(能力比p收缩:p能改内容+指向,s4都不能改),符合“能力强→能力收缩”的规则。// 本质:给指针“加双重限制”,是最安全的赋值。
}
4.引用
引用的定义:类型&引用变量名称=变量名称;
特点:
int a = 10;int& ra = a;//1.定义引用必须初始化//int& rb = NULL;//not 2.空引用 3.没有引用的引用double dx = 12.23;double& rx = dx;
引用作为形参代替指针:
void Swap(int* ra, int* rb)
{assert(ra != NULL && rb != NULL);int temp = *ra;*ra = *rb;*rb = temp;
}
void Swap(int& ra, int& rb)
{int temp = ra;ra = rb;rb = temp;
}
int main()
{int ar[10] = { 1,2,3,4,5,6 };int(&rar)[10] = ar;int a=10;int *p=&a;int *&rp=p;//对指针加引用int(*p)[10] = &ar;//数组引用
}
使用引用代替指针的好处就是不存在NULL引用,不需要判空,比指针安全。
