1. C++的特点
•在支持C的基础上,全面支持面向对象编程
•编程领域广泛,功能强大(最强大的编程语言,没有之一)
•标准保持更新,目前常用的基础标准为ISO C++98标准、ISO C++11标准等
•为数不多的支持底层操作的面向对象语言
•在面向对象的语言中执行效率极高
2. C++中的引用(reference)
1.1 基本使用
引用是一种简化的指针,引用相当于变量或常量的别名。操作引用与操作原变量相同。引用通常与后面的栈内存对象结合使用。
#include <iostream>
using namespace std;
int main()
{
int a = 1;
int& b = a; // b是a的引用
// 操作b和操作a相同
b++;
cout << a << " " << b << endl;
// 查看地址
cout << &a << " " << &b << endl; // 0x61fe88 0x61fe88
return 0;
}
1.2 性质
可以改变引用的值,但是不能再次成为其他变量的引用。
#include <iostream>
using namespace std;
int main()
{
int a = 1;
int& b = a;
int c = 2;
// 改变b的值
b = c;
cout << a << b << c << endl; // 222
cout << &a << endl; // 0x61fe78
cout << &b << endl; // 0x61fe78
cout << &c << endl; // 0x61fe74
return 0;
}
声明引用时,必须初始化。
初始化的值不能为NULL。
声明引用时,如果初始化的值是纯数值,需要使用const修饰引用,表示常引用,这样的引用数值不可变。
#include <iostream>
using namespace std;
int main()
{
const int &b = 123;
// b++; // 错误
cout << b << endl; // 123
cout << &b << endl; // 0x61fe88
return 0;
}
引用的指针:可以把引用的地址交给指针保存,此时指针指向的还是引用的原变量。
#include <iostream>
using namespace std;
int main()
{
int a = 1;
int& b = a;
int* c = &b; // c指向b,b就是a,相当于c指向a
cout << c << " " << &a << endl; // 0x61fe84 0x61fe84
return 0;
}
指针的引用:即指针也可以有“别名”
#include <iostream>
using namespace std;
int main()
{
int a = 1;
int *b = &a; // b是a的指针
int*& c = b; // c是b的引用
// 操作c和操作b是一样的
cout << b << " " << c << endl; // 0x61fe88 0x61fe88
(*c)++;
cout << a << endl; // 2
return 0;
}
const修饰的常引用不能改变引用的值,但是引用的原变量可以改变。
#include <iostream>
using namespace std;
int main()
{
int a = 1;
const int& b = a; // b是a的常引用
// b++; 错误
a++;
cout << a << " " << b << endl;
return 0;
}
指针和引用的区别:
1.引用必须初始化,指针不必.
2.引用初始化后不能被改变,指针可以改变所指的变量.
3.不存在指向空值的引用,但是存在指向空值的指针.
1.3 引用参数
如何交换两个数,写一个函数输入两个数字变量,功能是交换两个输入变量的值。
#include <iostream>
using namespace std
void swap1(int* a,int* b)
{
*a = *a ^ *b;
*b = *a ^ *b;
*a = *a ^ *b;
}
void swap2(int& a,int& b) // C++学得好
{
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
int main()
{
int a = 1;
int b = 2;
// swap1(&a,&b);
swap2(a,b);
cout << a << endl;
cout << b << endl;
return 0;
}
使用引用传递参数可以提升传递效率,因为不产生副本,引用参数参数应该在能被定义为const的情况下,尽量定义为const,以达到引用的安全性。
#include <iostream>
using namespace std;
void show(const int& a,const int& b)
{
cout << a << b << endl;
}
int main()
{
int a = 1;
int b = 2;
show(a,b);
return 0;
}
2. 初始化
#include <iostream>
using namespace std;
int main()
{
// C语言初始化
int a = 1;
int b = a;
// C++初始化
int c(1);
int d(c);
// C++11初始化
int e{1};
int f{e};
return 0;
}
{}初始化的方式也被称为通用统一初始化(一致性初始化),这是C++11的新语法,多了一个窄化警告的功能。
3. 输入
输入使用cin
#include <iostream>
using namespace std;
int main()
{
// C++的字符串类型
string a;
int b;
char c;
cout << "请输入一个字符串、一个整数和一个字符:";
// 连续输入给a,b,c
// 支持空格或回车断开
cin >> a >> b >> c;
cout << endl;
cout << "您输入的数据是:" << endl;
cout << a << endl;
cout << b << endl;
cout << c << endl;
return 0;
}
如果输入的字符串包含空格,则可以使用下面的方式:
#include <iostream>
using namespace std;
int main()
{
// C++的字符串类型
string a;
cout << "请输入一个字符串(包含空格):";
getline(cin,a); // 把cin的一行数据都给a
cout << "您输入的字符串是:" << endl;
cout << a << endl;
return 0;
}
4. 字符串类型 string(掌握)
string本身不是C++的基本数据类型,因此在使用前需要引入头文件 :#include <string>
需要注意的是引入头文件时,不能把头文件写成<string.h>,因为这是C语言的头文件。
string类型用于在大多数情况下代替char*,不需要担心内存是否足够与长度等问题。string内部集成了大量的操作函数可以处理字符串问题。
#include <iostream>
//#include <string>
using namespace std;
int main()
{
string str = "Hello";
// 取出单字符
cout << str[0] << endl; // H
cout << str.at(0) << endl; // H
cout << str << endl;
// 获取字符串长度(两种函数没有差别)
cout << str.length() << endl;
cout << str.size() << endl;
// 遍历字符串
// 1. for循环
for(int i=0;i<str.size();i++)
{
cout << str.at(i) << endl;
}
// 2. C++11 for-each(增强型for循环)
for(char i:str)
{
cout << i << endl;
}
// 3. 迭代器(略)
return 0;
}
使用[]和at函数都可以取出单个字符,建议使用at函数:
1. at函数更加安全,越界后终止运行
#include <iostream>
using namespace std;
int main()
{
string str = "Hello";
cout << str.at(10086) << endl; // 运行终止
cout << "主函数结束" << endl;
return 0;
}
2. []效率更高
#include <iostream>
using namespace std;
int main()
{
string str = "Hello";
cout << str[10086] << endl; // 运行不稳定
cout << "主函数结束" << endl;
return 0;
}
5. 函数
5.1 内联函数 inline
C++中引入内联函数的目的是为了取代C语言中宏定义函数。
内联函数使用关键字inline放在函数定义(不是声明)的前面,inline可以建议编译器进行主函数展开编译,如果生效,则可以提升程序的运行效率,因此消除了函数调用的额外开销。一般把长度较小(5行以内)、频繁使用且不包含复杂的控制语句的函数写为内联函数。
#include <iostream>
using namespace std;
inline void test()
{
int a = 1;
int b = 2;
cout << a+b << endl;
cout << a-b << endl;
}
void test2(); // 声明
inline void test2() // 定义
{
int a = 1;
int b = 2;
cout << a*b << endl;
cout << a/b << endl;
}
int main()
{
test();
test2();
return 0;
}
5.2 函数重载 overload(重点)
函数签名:函数名称、参数的个数和类型。
如果在C++中,“两个函数”的签名相同,编译器则会认为这是一个函数。
如果函数名称相同,但是签名不同(参数个数或类型不同),这样的函数就构成了函数重载。
#include <iostream>
using namespace std;
void print()
{
cout << "A" << endl;
}
void print(int a)
{
cout << "B" << a << endl;
}
void print(string s)
{
cout << "C" << s << endl;
}
//int print() 错误:二义性
//{
// cout << "A" << endl;
// return 1;
//}
int main()
{
print();
print("dfsfd");
print(23);
return 0;
}
5.3 参数默认(缺省)值(掌握)
C++允许给函数的参数设定默认值,调用时如果传入参数,则使用传入的参数;如果不传入参数,则使用默认值。
如果函数的声明与定义分离,默认值可以写在声明或定义处,但是只能出现一次。
向右(向后)原则:如果函数的某个参数被设置了默认值,其右边(后面)所有的参数都必须设定默认值。尽量不要把参数默认值与函数重载一起使用,因为新手很容易错乱。
#include <iostream>
using namespace std;
void print(int a = 1,int b = 2,int c = 3)
{
cout << a << b << c << endl;
}
void test(int a);
void test(int a = 1)
{
cout << a << endl;
}
void func1(string s1,string s2,string s3="AAA")
{
cout << s1 << s2 << s3 << endl;
}
void func2(string s1,string s2="AAA",string s3="BBB")
{
cout << s1 << s2 << s3 << endl;
}
int main()
{
print(); // 123
print(6); // 623
print(6,6); // 663
print(6,6,6); // 666
test(); // 1
func1("1","2");
func1("1","2","3");
func2("1");
func2("1","2");
func2("1","2","3");
return 0;
}
5.4 哑元函数(熟悉)
一个函数的参数只有类型没有名字,则这个参数就是哑元,这样的函数就是哑元函数。
#include <iostream>
using namespace std;
void print(string)
{
cout << "哑元函数" << endl;
}
int main()
{
// print(); 错误
print("为什么");
return 0;
}
哑元函数在特定的场景下会发挥作用,例如:
1. 可以使用这个参数强行重载函数
2. 保持函数的向前兼容特性