zoukankan      html  css  js  c++  java
  • C++基础

    C++

    一、C++简介

    1、C++语法特性?
    C语言是一种面向过程的语言,任何一个大事件都可以拆分为多个小事件。
    C++是一种面向对象的语言,任何一个事件都是某一个对象上的行为/属性。

    2、C++语法。
    C++是一种全新语法,除了继承了C语言的语法之外,还拓展关于数据类型、继承、多态等新语法。

    3、C++函数接口。
    C语言即使是相同的功能,也可以写出多个接口。
    C++语法提供了标准模板库(STL),它里面提供了一些通用的接口,全世界的人都使用同一个接口。

    二、书写第一个C++程序。

    1、创建一个C++工程文件。
    C++工程文件格式:xxx.cpp

    2、编辑代码。
    1)C++兼容C语言,也是从main函数开始执行,从main函数结束。

    2)如果要使用C++语法,那么就必须在文件开头包含标准头文件以及对应标准的命名空间。
    #include -> 标准头文件
    using namespace std; -> 标准命名空间(C++中,有很多工具都是放在这个命名空间中,如果想在C++代码中直接使用这些工具,那么就必须使用标准命名空间)
    (如果不使用命名空间,那么使用工具时,就必须在工具前面加上作用域符号)

    3)C++中使用cout这个工具来输出数据。

    4)endl相当于是\n

    #include <iostream>
    using namespace std;
    
    int main(int argc,char *argv[])
    {
    	cout << "helloworld" << endl;   //先输出helloworld,然后再换行。
    	return 0;
    }
    

    3、编译代码。

    C语言: gcc编译器 gcc my_first.c -o my_first
    C++: g++编译器 g++ my_first.cpp -o my_first

    4、执行代码。
    gec@ubuntu:/mnt/hgfs/GZ2119/07 C++/01/code$ ./my_first
    helloworld

    三、变量。

    1、变量的作用?
    给一段指定的内存空间起名字,方便操作这段内存。

    2、如何在C++程序中输出变量的值?

    #include <iostream>
    using namespace std;
    
    int main(int argc,char *argv[])
    {
    	cout << "helloworld" << endl;   //先输出helloworld,然后再换行。
    
    	int a = 10;
    	cout << "a = " << a << endl;
    
    	return 0;
    }
    

    四、常量。

    1、常量的作用?
    用于记录程序中不可修改的数据。

    2、C++定义常量方法有两种:
    1)宏常量。

    #include <iostream>
    using namespace std;
    
    #define DAY 7
    
    int main(int argc,char *argv[])
    {
    	DAY = 8;
    	cout << "一个星期有:" << DAY << "天" << endl;
    	return 0;
    }
    

    2)const修饰的变量。

    #include <iostream>
    using namespace std;
    
    int main()
    {
    	const int month = 12;   //变量
    	//month = 13;
    	cout << "一年有:" << month << "月" << endl;
    	return 0;
    }
    

    五、字符串。

    1、字符串作用?
    可以表示一串字符。

    2、在C++中有两种风格来表示字符串。
    C风格字符串:
    语法: char 数组名[] = "字符串值"

    C++风格字符串:
    语法: string 字符串名 = "字符串值"

    #include <iostream>
    using namespace std;
    
    int main()
    {
    	//1. C风格字符串
    	char str[] = "helloworld";
    	cout << str << endl;
    
    	//2. C++风格字符串
    	string str1 = "appletree";
    	cout << str1 << endl;
    
    	return 0;
    }
    

    六、转义符号。

    常用转义符号:
    '\n' -> 换行
    '\t' -> 水平制表,跳到下一个Tab键的位置

    #include <iostream>
    using namespace std;
    
    int main()
    {
    	//1. 换行符
    	cout << "helloworld\n";
    
    	//2. 水平制表
    	cout << "aaa\thelloworld" << endl;
    	cout << "a\thelloworld" << endl;
    	cout << "aaaaa\thelloworld" << endl;
    
    	return 0;
    }
    

    七、数据的输入。

    1、作用?
    从键盘获取一些数据。

    2、关键词。
    cin

    3、语法。
    cin >> 变量

    #include <iostream>
    using namespace std;
    
    //语法:
    //cin >> 变量
    
    int main()
    {
    	/*
    	//1. 整型
    	int a = 0;
    	cout << "请输入一个整型数据:" << endl;
    	cin >> a;
    	cout << "a = " << a << endl;
    
    	//2. 浮点型
    	double d = 0;
    	cout << "请输入一个浮点型数据" << endl;
    	cin >> d;
    	cout << "d = " << d << endl;
    
    	//3. 字符串
    	string s = "helloworld";
    	cout << "请输入一个字符串" << endl;
    	cin >> s;
    	cout << "s = " << s << endl;
    	*/
    
    	int a;
    	char b;
    
    	cin >> a;
    	cin >> b;
    
    	cout << "a = " << a << endl;
    	cout << "b = " << b << endl;
    
    	return 0;
    }
    

    八、递增递减运算符。

    1、作用:变量自身+1/-1。
    2、符号:++/--

    #include <iostream>
    using namespace std;
    
    int main()
    {
    	//1. 前置递增。
    	int a = 10;
    	++a;
    	cout << "a = " << a << endl;  //11
    
    	//2. 后置递增。
    	int b = 20;
    	b++;
    	cout << "b = " << b << endl;  //21
    
    	//3. 前置递增与后置递增有什么区别?
    	//前置递增:先让变量+1,然后再进行表达式运算。
    	int a2 = 10;
    	int b2 = ++a2 * 10;
    	cout << "a2 = " << a2 << endl; //11
    	cout << "b2 = " << b2 << endl; //110
    
    	//后置递增:先进行表达式运算,再让变量+1。
    	int a3 = 10;
    	int b3 = a3++ * 10;
    	cout << "a3 = " << a3 << endl; //11
    	cout << "b3 = " << b3 << endl; //100
    
    	//4. 连续递增。
    	int a4 = 10;
    	++(++a4);
    	cout << "a4 = " << a4 << endl; //12
    
    	int a5 = 10;
    	(a5++)++;   //在C++中,不支持连续的后置递增
    	cout << "a5 = " << a5 << endl;
    
    	return 0;
    }
    

    九、比较运算符。

    == 相等于 != 不等于
    < 小于 > 大于
    <= 小于或者等于 >= 大于或者等于

    #include <iostream>
    using namespace std;
    
    int main()
    {
    	/*
    	int a = 10;
    	int b = 20;
    
    	cout << (a==b) << endl;
    	cout << (a!=b) << endl;
    	cout << (a<b) << endl;
    	cout << (a>b) << endl;
    	cout << (a<=b) << endl;
    	cout << (a>=b) << endl;
    	*/
    
    	string s1 = "helloworld";
    	string s2 = "helloappletree";
    
    	cout << (s1==s2) << endl;
    	cout << (s1!=s2) << endl;
    	cout << (s1>s2) << endl;
    	cout << (s1<s2) << endl;
    	cout << (s1>=s2) << endl;
    	cout << (s1<=s2) << endl;
    
    	return 0;
    }
    

    结论:
    字符串比较大小:按照ascii码的大小来一一对比。

    十、逻辑运算符。

    1、作用:
    根据表达式真假,返回真值或者假值。

    2、符号。
    ! -> 非 !a 如果a为真,结果为假,如果a为假,则结果为真。
    && -> 与 a&&b 如果a与b都为真,结果就为真,否则为假。
    || -> 或 a||b 如果a与b有一个为真,则结果为真,二者都为假时,则结果为假。

    #include <iostream>
    using namespace std;
    
    int main()
    {
    	int a = 10;
    	int b = 10;
    	int c = 0;
    	int d = 0;
    
    	cout << !a << endl;   //0
    	cout << !!a << endl;  //1
    
    	cout << (a&&b) << endl;  //1
    	cout << (a||b) << endl;  //1
    
    	cout << (a&&c) << endl;  //0
    	cout << (a||c) << endl;  //1
    
    	cout << (c&&d) << endl;  //0
    	cout << (c||d) << endl;  //0
    
    	return 0;
    }
    

    十一、内存分区模型。

    1、在C++程序执行时,将内存大方向可以划分为4个区域。
    1)代码区:存放函数的二进制代码,由操作系统来进行管理。
    2)全局区:存放着全局变量、静态变量、以及常量。
    可以理解为: rodata区、bss段、data段统一划分到全局区。
    3)堆区: 由工程师手动分配与释放,若不释放,程序结束时由操作系统来回收。
    4)栈区: 由编译器自动分配与释放,存放的是函数形式参数,局部变量。

    2、内存四区意义?
    不同区域存放不同的数据,赋予不同的生命周期,给我们更大的灵活编程。

    十二、程序运行前。

    在程序编译后,生成一个可执行程序,未执行这个程序之前分为两个区域:
    1、代码区:
    存放CPU执行的机器指令 -> 其实就是指0101这种数据。

    代码区是共享的,共享的目的是对于频繁被执行的代码,只需要在内存中有一份代码即可。
    无论执行了多少次这段代码,都是使用同一个代码。

    代码区是只读的,使其只读的原因是防止程序意外地修改它的指令。

    2、全局区:
    全局变量与静态变量存放在此。
    全局区还包含了常量区、字符串常量、其他常量(const修改的变量)在存放在此。
    该区域的数据在程序结束之后由操作系统来释放。

    #include <iostream>
    using namespace std;
    
    //2. 创建全局变量。
    int g_a = 10;
    int g_b = 20;
    
    //4.2 const修饰的全局变量 -> 全局常量
    const int c_g_a = 10;
    const int c_g_b = 20;
    
    int main()
    {
    	//1. 创建局部变量。
    	int a = 10;
    	int b = 20;
    
    	cout << "&a = " << &a << endl;
    	cout << "&b = " << &b << endl;       //局部变量: 栈区
    
    	cout << "&g_a = " << &g_a << endl;
    	cout << "&g_b = " << &g_b << endl;   //全局变量: 全局区
    
    	//3. 创建静态变量。
    	static int s_a = 10;
    	static int s_b = 20;
    
    	cout << "&s_a = " << &s_a << endl;
    	cout << "&s_b = " << &s_b << endl;   //静态变量: 全局区
    
    	//4. 常量区
    	//1>. 字符串常量。
    	cout << "string addr = " << &"helloworld" << endl;   //字符串常量: 全局区
    
    	//2>. const修饰变量。
    	//const修饰的全局变量  -> 全局常量    
    	cout << "&c_g_a = " << &c_g_a << endl;
    	cout << "&c_g_b = " << &c_g_b << endl;   //全局常量: 全局区
    	
    	//const修饰的局部变量  -> 局部常量
    	const int c_l_a = 10;
    	const int c_l_b = 20;
    
    	cout << "&c_l_a = " << &c_l_a << endl;
    	cout << "&c_l_b = " << &c_l_b << endl;   //局部常量: 栈区
    
    	return 0;
    }
    
    运行结果:
    gec@ubuntu:/mnt/hgfs/GZ2119/07 C++/01/code$ ./space
    &a = 0x7ffe3f008ff8
    &b = 0x7ffe3f008ffc
    &g_a = 0x601070
    &g_b = 0x601074
    &s_a = 0x601078
    &s_b = 0x60107c
    string addr = 0x400c47
    &c_g_a = 0x400c04
    &c_g_b = 0x400c08
    &c_l_a = 0x7ffe3f009000
    &c_l_b = 0x7ffe3f009004
    

    结论:
    不在全局区:
    局部变量
    使用const修饰的局部变量(局部常量)

    在全局区:
    全局变量
    静态变量
    常量:
    字符串常量
    使用const修饰的全局变量(全局常量)

    十三、程序运行后。

    栈区: 由编译器自动分配释放,存放函数的形式参数值,局部变量等。
    注意: 不要返回局部变量的地址,栈区开辟的数据由编译器自动释放。

    #include <iostream>
    using namespace std;
    
    //栈区: 形参、局部变量。
    //注意: 不要返回局部变量的地址。
    
    int *fun(int b)  //b就是形式参数,存放在栈区
    {
    	int a = 10;  //a是局部变量,是存放在栈区中。    --> 开始申请a的空间
    	return &a; 
    						       --> 开始释放a的空间 
    }
    
    int main()
    {
    	int *p = fun(1);
    	cout << "p = " << p << endl;    //&a   0/NULL    -> 到这里,a的空间已经释放完了,所以不要再访问a的空间
    							 -> 为了防止你再次访问,编译器就不会返回&a给你,返回NULL。
    	cout << "*p = " << *p << endl;  //10   段错误
    
    	return 0;
    }
    

    堆区:由工程师分配和释放,若不释放,程序结束时由操作系统来回收。
    在C++中主要利用new在堆区开辟空间。

    #include <iostream>
    using namespace std;
    
    int *func()
    {
    	//利用new关键词,可以将数据开辟到堆区。
    	int *a = new int(10);   //在堆区申请一个int类型数据大小的空间,并且将10赋值给这个空间。
    	return a;
    }
    
    int main()
    {
    	int *p = func();
    	cout << "p = " << p << endl;
    	cout << "*p = " << *p << endl;   //10
    
    	return 0;
    }
    
    运行结果:
    gec@ubuntu:/mnt/hgfs/GZ2119/07 C++/01/code$ ./new
    p = 0x1d35c20
    *p = 10
    

    结论:
    在函数返回时,堆区空间不会释放。

    十四、new操作符。

    C++中利用new操作符在堆区开辟数据。
    堆区中开辟的数据,由工程师手动开辟,手动释放、释放利用操作符delete。
    语法:new 数据类型
    利用new创建的数据,会返回该数据对应类型的指针。

    1、 堆区的基本语法示例。

    #include <iostream>
    using namespace std;
    
    int *func()
    {
    	//在堆区中创建整型数据。
    	int *p = new int(10);
    	return p;
    }
    
    int main()
    {
    	int *p = func();
    	cout << "*p = " << *p << endl;  //10
    
    	//堆区的数据由用户主动释放。
    	delete p;
    	p = NULL;
    
    	cout << "*p = " << *p << endl;  //段错误
    
    	return 0;
    }
    

    2、在堆区利用new开辟数组。

    #include <iostream>
    using namespace std;
    
    int main()
    {
    	//创建10个整型数据在堆区。
    	int *arr = new int[10];   //10代表数组有10个元素。
    
    	int i;
    	for(i=0;i<10;i++)
    	{
    		arr[i] = i + 100;  //给10个元素赋值 100~109
    	}
    
    	for(i=0;i<10;i++)
    	{
    		cout << arr[i] << endl;
    	}
    
    	//释放数组时,需要加[]才可以。
    	delete[] arr;
    
    	return 0;
    }
    

    十五、引用的基本使用。

    1、引用作用?
    给变量起别名。

    2、语法。
    数据类型 &别名 = 原名

    #include <iostream>
    using namespace std;
    
    //引用作用:给变量起别名。
    //引用语法:数据类型 &别名 = 原名
    
    int main()
    {
    	int a = 10;
    
    	//创建引用
    	int &b = a;
    
    	cout << "a = " << a << endl;  //10
    	cout << "b = " << b << endl;  //10
    
    	b = 100;
    
    	cout << "a = " << a << endl;  //100
    	cout << "b = " << b << endl;  //100
    
    	return 0;
    }
    

    十六、引用注意事项。

    1、引用必须初始化。
    2、引用在初始化后,不可以改变。

    #include <iostream>
    using namespace std;
    
    //引用注意事项。
    //1、 引用必须初始化。
    //2、 引用在初始化之后,不可以改变。
    
    int main()
    {
    	//1. 引用必须初始化。
    	//int &c;   //编译出错,引用必须初始化,必须要引用一块合法并且存在的空间。
    	
    	//2. 引用在初始化之后,不可以改变。
    	int a = 10;
    	int b = 20;
    
    	//创建引用。
    	int &c = a;   //一旦初始化之后,就不可以更改。(c永远都是a的别名)
    
    	c = b;  //这是赋值操作
    		//不是让c去做b的别名
    
    	cout << "a = " << a << endl;  //20    
    	cout << "b = " << b << endl;  //20    
    	cout << "c = " << c << endl;  //20    
    
    	return 0;
    }
    

    十七、引用做函数参数。

    作用:函数传参时,可以利用引用的技术让形参修饰实参。
    优点:可以简化指针修饰实参的方法。

    #include <iostream>
    using namespace std;
    
    //1. 值传递
    /*
    void mySwap01(int a,int b)
    {
    	int temp = a;
    	a = b;
    	b = temp;
    }
    */
    
    //2. 地址传递
    /*
    void mySwap02(int *a,int *b)
    {
    	int temp = *a;
    	*a = *b;
    	*b = temp;
    }
    */
    
    //3. 引用传递
    void mySwap03(int &a,int &b)  //别名  //  int &a = a   int &b = b
    							  //形式a虽然是一个形参,但是实际上代表也是实参。
    {
    	int temp = a;  //所以这样调换,操作就是实参。
    	a = b;
    	b = temp;
    }
    
    int main()
    {
    	int a = 10;
    	int b = 20;
    
    	//mySwap01(a,b);   不能交换 -> 因为交换的是形式参数的,形式参数的修改并没有影响到实参,所以实参依然是10和20。
    	//mySwap02(&a,&b); 能交换   -> 因为通过形参来解引用访问到实参,所以修改的是实参的值,所以可以更换。
    	mySwap03(a,b);     能交换   -> 因为使用引用方式来传递,实参是原名,形参是别名,所以修改形参的值,其实就是修改实参的值。
    
    	cout << "a = " << a << endl;  //10   20    20
    	cout << "b = " << b << endl;  //20   10    10
    
    	return 0;
    }
    

    十八、引用做函数返回值。

    作用:引用是可以作为函数返回值存在的。

    注意事项:
    1、 不要返回局部变量的引用。
    2、 函数的调用可以作为左值存在。

    #include <iostream>
    using namespace std;
    
    //引用作为函数返回值
    //1、 不要返回局部变量的引用。
    //2、 函数的调用可以作为左值的存在。
    
    //int    --> 返回的是10(本体的值)
    //int&   --> 返回的是a (本体)
    
    int& test01()
    {
    	//1、不要返回局部变量的引用。
    	//int a = 10;  //局部变量
    	static int a = 10;
    	return a;   //其实就是返回a的本体。   
    }
    
    int main()
    {
    	int &ret = test01();
    	cout << "ret = " << ret << endl;  //10
    
    	//2. 函数的调用可以作为左值的存在。
    	test01() = 1000;   //a = 1000
    	cout << "ret = " << ret << endl; //1000
    
    	return 0;
    }
    

    十九、引用的本质。

    本质:引用本质在C++中内存实现其实就是一个指针常量。

    解析:
    情况一:

    int a = 10;
    int b = 20;
    const int *ref = &a;   等价于    int const *ref = &a;    
    

    结论:
    可以再赋值给别的地址给ref,但是不可以通过ref去修改ref指向的值。
    ref = &b; -> 正确
    *ref = 20; -> 错误

    情况二:

    int a = 10;
    int b = 20;
    int * const ref = &a;   (ref一旦赋值了&a,那么ref就永远等于&a)    -> 指针常量
    

    结论:
    不可以再赋别的地址的值给ref,但是可以通过ref去修改ref指向的值。
    ref = &b; -> 错误
    *ref = 30; -> 正确

    #include <iostream>
    using namespace std;
    
    void func(int &ref)   // int &ref = &a
    {
    	ref = 100;  //  *ref = 100
    }
    
    int main()
    {
    	int a = 10;
    
    	//创建引用,ref是别名,a是原名
    	//系统看到这句话之后,会自动转换成 int * const ref = &a;
    	//ref是一个指针常量,一旦把&a的这个地址赋值给ref这个指针之后,ref就不能指向别的东西了。
    	//这也解析了为什么引用初始化了值之后,不能修改。
    	int &ref = a;
    
    	//系统看到这句话之后,发现ref是引用来的,就会自动帮我们转换成: *ref = 20;
    	ref = 20;
    
    	cout << "a = " << a << endl;
    	cout << "ref = " << ref << endl;
    
    	func(a);
    	
    	cout << "a = " << a << endl;  //100
    	cout << "ref = " << ref << endl;
    
    	return 0;
    }
    ///////
    a = 20
    ref = 20
    a = 100
    ref = 100
    

    二十、常量引用。

    作用:常量引用主要用于修饰形参,防止误操作。
    在函数形参列表中,可以使用const修饰形参,防止形参改变实参。

    #include <iostream>
    using namespace std;
    
    //常量引用
    //一般使用场景:修饰形式参数。
    
    void show_value(const int &val)   //  const int &val = height;
    {
    	//加了const之后,val就可以打印,但是不可以修改。
    	//val = 160;
    	cout << "val = " << val << endl;
    }
    
    int main()
    {
    	//int &ref = 10;  //错误
    	//引用必须引用一块合法的空间,如果这样写可以的话,意味ref=20也是成立,但是这样做,意味着10=20,就相当于是给常量赋值。
    	 /*(1)只有一个const,如果const位于*左侧,表示指针所指数据是常量,不能通过解引用修改该数据;指针本身是变量,可以指向其他的内存单元。
    
      (2)只有一个const,如果const位于*右侧,表示指针本身是常量,不能指向其他内存地址;指针所指的数据可以通过解引用修改。*/
    	//const int &ref = 10;  //正确    -> 只看得到别名,看不到原名
    	//系统看到这句话之后,会自动帮我们转换成以下的几句话:
    	/*
    	int temp = 10;                  -> 既看得到原名,也看得到别名。
    	const int &ref = temp;
    	*/
    
            //ref = 20;  //编译出错,ref是只读的。
    
    	int height = 170;
    	show_value(height);
    
    	return 0;
    }
    
  • 相关阅读:
    Reborn
    个人总结
    第十六周个人进度条
    梦断代码阅读笔记03
    第十五周个人进度条
    第十四周个人进度条
    第十三周个人进度条
    冲刺9
    冲刺8
    事后诸葛亮会议
  • 原文地址:https://www.cnblogs.com/hyxk/p/15590955.html
Copyright © 2011-2022 走看看