从堆上申请空间
#include<malloc.h>
int *p = (int )malloc(10sizeof(int));//malloc返回的是无类型
free(p);//释放内存,不然会造成内存泄漏

命名空间:用户自己定义的作用域

namespace N{
//变量
int a;
//函数
}
int a;//不冲突
  1. 命名空间可以嵌套
  2. 在一个工程中,可以出现多个相同名称的命名空间
  3. 命名空间中成员的使用方式
方式一:命名空间名字::成员名字
namespace N{
//变量
int a =10;
//函数
int ADD(int right,int left){
return right+left;
}
int a=20;//不冲突
int main(){
int a =30;
printf("%d",a);//30
printf("%d",::a);//20 作用域运算符::
printf("%d",N::a);//10//打印作用域为N的变量
N::ADD(10,20);
方式二:using N::a;

(假设:命名空间中某些成员在当前文件中被频繁使用)

namespace N{

//变量

int a =10;

//函数

int ADD(int right,int left){

return right+left;

}


using N::a;
int main(){
printf("%d",N::a);//10
printf("%d",N::a);
printf("%d",N::a);
printf("%d",N::a);
printf("%d",a);//10

N::ADD(10,20);
方法三:using namespace N;

//可以将N命名空间中所有成员当成本文件中的全局变量    缺点:易发生冲突

(当前命名空间中好些成员都要在当前文件中使用)

输入输出

  • cin输入
  • cout输出
  • endl表示换行
命名空间的使用
方式一
#include<iostream>
using namespace std;
int main() {
	int a ;
	double b;
	char c ;
//	cin >> a;
//cin >> b;
//	cin >> c;//cin输入
	cin >> a >> b >> c;
	cout << "hello world" << endl;//cout输出
	cout << a <<" "<< b <<" " <<c << endl;//endl表示换行

	return 0;
}

方式二
#include<iostream>
using std::cin;
using std::cout;
using std::endl;
int main() {
	int a ;
	double b;
	char c ;
//	cin >> a;
//cin >> b;
//	cin >> c;//cin输入
	cin >> a >> b >> c;
	cout << "hello world" << endl;//cout输出
	cout << a <<" "<< b <<" " <<c << endl;//endl表示换行

	return 0;
}


方式三
#include<iostream>
int main() {
	int a ;
	double b;
	char c ;
//	cin >> a;
//cin >> b;
//	cin >> c;//cin输入
std::cin >> a >> b >> c;
	std::cout << "hello world" << std::endl;//cout输出
	std::cout << a <<" "<< b <<" " <<c << std::endl;//endl表示换行

	return 0;
}

函数重载

函数的一种特殊情况,C++允许在同一作用域下,声明函数名相同,但形参不同的情况,如果类型不完全匹配,编译器会有隐式类型转换

#include<iostream>
//#using std::cout;
//#using std::endl;
int ADD(int left, int right) {
	return left + right;
}
double ADD(double left, double right) {
	return left + right;
}
int main() {
	int a =ADD(10, 20);
	double b =ADD(10.2, 3.4);
	
	std::cout<<a<<" "<<b <<std::endl;
	return 0;
}
#include<iostream>
using namespace std;
//作用域不同,无法形成重载
namespace N {
	void func() {
		cout << "func:int+double" << endl;
	}
}
void func() {
	cout << "func()" << endl;
}
//如果两个参数仅仅是因为返回值类型不同,无法构成重载
int func() {
	return 0;
}
//参数不同
void func(int a) {
	cout << "func(int)" << endl;
}
void func(int a,double b) {
	cout << "func(int+double)" << endl;
}
//参数不同
void func(int a,int b) {
	cout << "func(int+int)" << endl;

}
//次序不同
void func(double a, int b) {
	cout << "func(double+int)" << endl;
}

先传参,再分配空间

引用:类型& 别名 = 变量;
  • 引用作为方法的返回值,一定不能返回栈上的空间,比如:局部变量。返回的实体不能随着方法的结束而销毁。
  1. 引用在定义时必须初始化
  2. 一个变量可以有多个引用
  3. 引用一旦引用一个实体,再不能引用其他实体
void Swap(int& left, int& right)
{
 int temp = left;
 left = right;
 right = temp;
}
int& Count()
{
 static int n = 0;
 n++;
 // ...
 return n;
}

指针和引用的区别:概念+性质+使用

  1. 引用概念上定义一个变量的别名,指针存储一个变量地址。
  2. 引用在定义时必须初始化,指针没有要求。
  3. 引用不能引用其他实体,但是指针可以指向任何一个实体
  4. 没有NULL引用
  5. 引用的大小是引用实体的大小
  6. 引用比指针用起来更安全
  7. 有多级指针,没有多级引用

  • 指针:取地址,解引用的操作需要用户自己完成
  • 引用:取地址,解引用的操作是由编译器完成

在底层,引用按照指针来处理,引用变量是有空间的,空间中存储的是实体的地址。

c/c++程序通过预处理、编译、汇编、链接

内联函数

  • 目的:解决c语言中宏函数不足----->#define出来的内容将其称为宏,在预处理阶段,会被预处理器替换的。
  • 宏常量:#define MAX_SIZE 100
  1. 优点:代码的可读性高,一改全改,程序的可维护性高
  2. 缺点:缺少参数类型检测
  • 在C语言中,const修饰的内容不是常量,而是不能被修改的变量。
  • C++中扩展了const的属性,const修饰的已经是常量,const修饰的常量具有宏替换的作用(发生在编译时)。
#include<iostream>
int main() {
	const int a = 10;//在编译阶段a已经成为10
	int* pa = (int*)&a;
	*pa = 100;
	std::cout << a << std::endl;//std::cout << 10 << std::endl;
	std::cout << *pa << std::endl;
	return 0;
}
  • 宏函数:#define MAX(a,b) a>b?a:b
  1. 优点:在预处理阶段会用宏体替换宏函数,替换之后少了函数调用的参数压栈,开辟栈帧等开销,提高程序的运行效率
  2. 缺点:不会进行类型检查,容易代码膨胀,增加代码长度,无法调试。

c++中宏函数被inline修饰的内联函数替换(时间换空间)——在编译阶段,编译器会用内联函数体来替换函数的调用,可以调试进行参数类型检测,没有副作用

注意:在debug模式下,内联函数默认不会展开

inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。

#include<iostream>
inline int ADD(int a,int b) {
	return a + b;
}
int main() {
	int a = 10;
	int b = 20;
	int ret = 0;
	ret = ADD(a,b);
	std::cout << ret <<std:: endl;
	return 0;
}

auto关键字

auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。

int main(){
int a = 10;
auto b =10,e = 11 ,f = 12;
auto c = 12.34;
auto d = 'a';
auto e = TestAtuo();
auto pa = &a; == auto *pa = &a;
auto &ra = a;//引用必须加7
cout<<typeid(b).name()<<endl;
cout<<typeid(c).name()<<endl;
cout<<typeid(d).name()<<endl;
cout<<typeid(e).name()<<endl;
  • 使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型。
  • auto不能定义函数的参数和数组

for循环(基于范围的for循环)

  • 注意:与普通循环类似,可以用continue来结束本次循环,也可以用break来跳出整个循环。
#include<iostream>
int main() {
	int array[] = { 1,2,3,4,5 };
	//在循环过程中,e是array数组中每个元素的一份拷贝
	for (auto e : array)
	{
		std::cout << e << std::endl;

	}
//在循环中,e是array数组中每个元素的别名
	for (auto &e : array)
	{
		e *= 2;

	}
	for(auto m :array)
		std::cout << m << std::endl;
	std::cout << std::endl;
	return 0;
}

指针空值nullptr

  • NULL实际是一个宏
int *pa = NULL;
int *pa = nullptr;//推荐