本系列是对C+premier笔记的补充,基于黑马C++和浙大C++。
命名空间
- std是C++标准命名空间,引用std的方式有三种,方式三最方便。注意C中不区分命名空间,只有一个全局作用域,标识符可能发生冲突。
- ::是作用域运算符,指明作用域
#include<iostream>
//using std:cout 方式二
using namespace std; //方式三
int main() {
//std::cout 命名空间:: 方式一
cout << "HelloWorld" << endl;
return 0;
}
命名空间可以嵌套定义,但要注意,子命名空间的变量必须引到底,引当前命名空间并不会引子命名空间的变量,比如当前命名空间和子命名空间有重名变量,那就回有歧义。
namespace {
...
}
using name::varaible//使用命名空间中某个变量
using namespace;//使用命名空间中所有变量
using namespace1:: namespace2; //嵌套调用
C+对C的一些增强
- 实用性增强 C+变量随用随定义,不需要像C得在作用域开始时定义。
- 变量监测增强,同一个/全局作用域不能重复定义变量,但是可以嵌套定义,子作用域相当于覆盖掉全局定义的变量。
- struct增强,定义之后创建对象new不需要struct关键词(相当于类了),struct可以有成员函数,可以继承和多态。
- 方法必须有类型,void或者有返回值类型。
- 加了bool,占1字节,true or false。
三目运算符增强
C+中三目运算符是变量,可以被赋值(可以作为左值),注意,如果返回值里面有常量就不行。
int a = 10;
int b = 20;
(a < b ? a : b) = 30;
const增强
1.C+const是真常量,不能通过*地址进行修改。
//2.C++ const真常量
int *p;
const int a = 10;
int* x = (int*) & a;
*x = 20;
cout << a << " " << *x; // out: 10 20
如上,a的值并没有修改,这是因为C+中const的定义被放到了符号表中,以键值对存储(在只读区,压根没有内存地址),在对a取地址的时候实际上没意义,如果强转会临时开辟一个temp变量(值和a一样)让x指向它,所以对x修改并不是对a修改。
2.指针常量和常量指针。
- 常量指针,常量的指针,指向常量的可变指针,指针(内存地址)可以改变指向其他地址,但指针地址里的内容是常量不能变。
- 指针常量。指向变量的不可变指针,指针本身是常量不能改变指向,地址存的内容可以变。
- 指向常量的指针常量,指向和存的内容都不能变。
- 常量一定要初始化。
- 别记常指针,说是谁的都有。
//3.指针常量,常量指针
//第⼀个第⼆个⼀样 代表⼀个常整形
const int a = 10;
int const b = 10;
//第三个 常量指针(所指向的内存数据不能被修改,但是本⾝可以修改)
const int c_1 = 0;
const int* c = &c_1; //常量指针注意初始化指向的得是常量
int const* c_2 = &c_1; //const默认优先作用左边的,左边没有作用右边的,一般写上一行这种,编译器认为是一样的
//第四个 指针常量(指针变量不能被修改,但是它所指向内存空间可以被修改)
int d_1 = 10;
int* const d = &d_1; //初始化
//第五个 指向常量的指针常量(指针和它所指向的内存空间,均不能被修改)
const int e_1 = 10;
const int* const e = &e_1;
}
3.const和define
两者类似,但是define的替换发生在预处理阶段(预处理器纯文本替换),const发生在编译阶段(编译器提供类型检查和作用域检查)
4.const内存分配 一下情况会为const常量分配内存:
- const常量为全局extern。
- 使用&取常量的地址,会开辟临时内存。
- 使用常量给常量引用初始化,C+开辟空间并将引用名作为这段空间别名。
枚举增强
C枚举本质是整形,所以枚举变量可以用整形赋值,C+中不允许偷懒,只能用枚举元素初始化枚举变量,想用整形就得强转。
//enum test {
// AAA,
// BBB
//};
test aa =(test)1;
test bb = BBB;
引用
C不能对变量起别名,C+可以。
int& a= b; //a是b的别名
- 引用没有定义,类型与原类型一致(常量引用是例外),不分配内存,地址和绑定的变量相同
- 声明必须初始化,不能改变
- 引用可以再次引用,就是某个变量的多个别名
- &前面有数据类型就表示引用,其余都是取址符
引用本质
引用的本质是一个指针常量,编译器隐藏了解引用和&取地址过程(定义省了&,用的时候省了)
引用传参
引用可以做函数参数传递,方法有三种传参方式:
- 值传递
- 引用传递
- 地址传递(指针)
引用作为函数返回值
引用可以作为函数的返回值,但不要返回局部变量的引用,避免外部再次引用局部变量而此时局部变量已经销毁出现问题(静态变量或者全局变量可以,不会被销毁)
引用作为函数的返回值时,是某个变量的别名,int等其他返回值返回是值拷贝,因此当使用引用作为函数返回值时可以做左值。
指针的引用
可以用一级指针的引用代替二级指针。
常量引用
一般用在形参,限制其只读。
int a = 10;
const int& b = a;
cout << &a << " "<< &b << endl;
a = 20;
cout << b << endl;
上述代码说明了一件事,常量引用类型可以不匹配(指可以给常量引用绑定变量),只限定了不能通过常量引用b修改a,a变了b也会变是拦不住的。同一类型(都是int)是这样的。
double a = 10.4;
const int& b = a;
const double& c = a;
a = 20.4;
cout << b << " " << c << endl;
return 0;
当是真正的类型不匹配(double->int),开辟了临时变量,这时候改a,c是不会变的,其他去看Primer笔记。
浙大C++
const
使用普通指针定义char数组是不允许的,"Hello World"是个常量在代码段,不能进行修改,必须用常量指针(普通指针不能指向常量),用char s[]=会先把helloworld拷贝到栈区,就是可以修改的。
const + 对象,里面的成员变量都不能修改,对应就得调用const的方法保证不被修改,同时初始化要对所有变量赋初值。
类里面的const成员一定得在构造函数里初始化。
函数加const,相当于this是const,因此可以构成重载(参数列表不同)。
引用
C++有三种地方放对象,栈,堆,全局数据区,三种取对象,指针,直接变量,引用。Java是只有一个堆,所以*给省掉了,C#也有可能的,去看看。
从右向左看,先碰到的是变量的类型,所以没有引用的指针(引用不是个对象),但有指针的引用。
向上造型-里氏代换原则-java的对象上转型-多态基础
子类可以替换掉父类对象使用。因为有完全相同的数据结构,指针指向是一样的(只看相同的一部分),即向上造型。注意只是,把子类看成父类,子类对象的东西都还在,不是转换。
后续内容合并到思维导图中,不在此更新了