目录
从C到C++
1、 引用(掌握)
1.1 概念
引用从一定程度上讲是指针的平替,几乎被所有的面型对象编程语言所使用。引用相当于对某一目标变量起一个“别名”。
操作引用与操作原变量完全一样。
【问题】指针和引用的区别?
#include <iostream>
using namespace std;
int main()
{
int a = 1;
// b是a的引用
int &b = a;
cout << a << " " << &a << endl; // 1 0x61fe88
cout << b << " " << &b << endl; // 1 0x61fe88
return 0;
}
1.2 引用的性质
可以改变引用的值,但是不能再次成为其他变量的引用。
#include <iostream>
using namespace std;
int main()
{
int a = 1;
// b是a的引用
int &b = a;
int &c = a;
b = c; // 只是赋值,不是引用,b还是a的引用
a = 2;
cout << a << " " << &a << endl; // 2 0x61fe88
cout << b << " " << &b << endl; // 2 0x61fe88
cout << c << " " << &c << endl; // 2 0x61fe88
return 0;
}
● 声明引用时,必须要初始化
#include <iostream>
using namespace std;
int main()
{
int a = 1;
// int &b; // 引用必须要初始化
cout << a << " " << &a << endl; // 2 0x61fe88
return 0;
}
● 声明引用时,不能初始化为null
#include <iostream>
using namespace std;
int main()
{
int a = 1;
// int &b = NULL; // 错误,引用不能初始化null
// int &b = nullptr; // 错误,引用不能初始化为nullptr
cout << a << " " << &a << endl; // 2 0x61fe88
return 0;
}
● 声明引用的时候,初始化的值可以是纯数值,但是此时需要使用const关键字修饰,表示该引用为常量引用,这样引用的值不可变。
#include <iostream>
using namespace std;
int main()
{
const int &b = 12; // 常量引用
// b = 222; // 错误,常量引用的数值不能被改变
cout << b << " " << &b << endl;
return 0;
}
● 可以将变量引用的地址赋值给一个指针,此时指针指向还是原来的变量。
#include <iostream>
using namespace std;
int main()
{
int a = 1;
int &b = a;
int *c = &b; // c同时指向了A和B
cout << a << " " << &a << endl; // 1 0x61fe84
cout << b << " " << &b << endl; // 1 0x61fe84
cout << *c << " " << c << endl; // 1 0x61fe84
return 0;
}
● 可以使用const修饰引用,此时如果原变量的值改变,引用的值也改变。
#include <iostream>
using namespace std;
int main()
{
int a = 2;
const int &b = a;
// b = 32; // 错误b是只读的
a++;
cout << a << " " << &a << endl; // 3 0x61fe88
cout << b << " " << &b << endl; // 3 0x61fe88
return 0;
}
1.3 引用参数
【思考】
写一个函数,函数有两个参数a和b,函数的功能是交换两个传入的参数原来变量的值。
#include <iostream>
using namespace std;
// 操作的是拷贝的副本,不符合需求
void test(int a,int b)
{
int temp = a;
a = b;
b = temp;
cout << "a =" << a << endl;
cout << "b =" << b << endl;
}
// C语言 再C++中不推荐这样写
void test1(int *a, int *b)
{
*a = *a ^ *b;
*b = *a ^ *b;
*a = *a ^ *b;
}
// C++编程方式,符合需求
void test2(int &a, int &b)
{
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
int main()
{
int a1 = 1;
int b1 = 2;
test2(a1,b1);
cout << a1 << endl;
cout << b1 << endl;
return 0;
}
引用作为参数进行定义的时候,在参数传递时,是不会产生副本的,这样会提高运行效率。我们在正常编程当中,建议使用引用进行传递参数。
引用参数,在不参与计算的情况下,我们建议使用const进行修饰,以达到引用的安全性。防止参数在函数内进行不必要的操作,或者是误操作。
2、 赋值(熟悉)
通常编程中使用=进行赋值操作,C++新增了以下赋值语法。
#include <iostream>
using namespace std;
int main()
{
int a(10); // 相当于 int a = 10;
// a(20); // 只能用于初始化
cout << a << endl;
int b(a); // int b = a;
cout << b << endl;
int c(a+b); // int c = a + b;
cout << c << endl;
return 0;
}
在C++11中对上述写法进行了升级。
#include <iostream>
using namespace std;
int main()
{
double b = 3.14;
int b1 = b;
cout << b1 << endl; // 3
int b2(b);
cout << b2 << endl; // 3
int b3{b};
cout << b3 << endl; // 3
return 0;
}
升级:对数据窄化做出警告。
3、 键盘输入(熟悉)
可以使用cin把用户在命令行中的内容赋值到变量中。
cin和cout一样,都属于头文件iostream中的标准输入输出流。
#include <iostream>
using namespace std;
int main()
{
int a;
// C++的字符串是string
string str;
cout << "请输入一个数字和字符串" << endl;
cin >> a >> str; // 接收键盘输入,一个整数和字符串,可以连续操作
cout << a << str << endl;
return 0;
}
如果cin输入的字符串需要包含空格,则可以使用下面的方式:
#include <iostream>
using namespace std;
int main()
{
// C++的字符串是string
string str;
cout << "请输入字符串,可以包含空格,输入完成后点击回车" << endl;
getline(cin,str); // 第二个参数只能是string类型
cout << str << endl;
return 0;
}
4、 string字符串类(掌握)
string不是C++的基本数据类型,它是一个C++标准库中的字符串类,使用时需要引入对应的头文件,#include<string>,而不是string.h.
string在绝大多数情况下,可以代替C语言中字符串,不必担心内存是否足够字符串长度等等。其中内部还包含了很多字符串处理函数,可以完成各种情况下的字符串处理功能。
string和C语言相同,字符串编码使用ASCII编码,不支持中文。
#include <iostream>
using namespace std;
int main()
{
string str = "helloworld";
cout << str << endl;
cout << str.size() << endl; // 10
cout << str.length() << endl; // 10
cout << str[1] << endl; // e
cout << str.at(1) << endl; // e
return 0;
}
两种方式都可以,但是在C++当中,更推荐你使用at函数,原因时at函数更安全。但是[ ]的方式效率更高。
#include <iostream>
using namespace std;
int main()
{
string str = "helloworld";
cout << str[100] << endl; // 输出一个越界数据
cout << str.at(100) << endl; // 会报一个异常,程序运行停止
cout << "hello" << endl;
return 0;
}
string类支持多种遍历方式
● 普通循环(以for循环为主)
● C++11:for each循环
#include <iostream>
using namespace std;
int main()
{
string str = "helloworld";
// 以for循环的方式进行输出字符串
for(int i = 0; i < str.length(); i++)
{
cout << str.at(i);
}
cout << endl;
// 以 for each的方式进行循环遍历字符串
for(char i:str)
{
cout << i;
}
return 0;
}
字符串与数字转换
#include <iostream>
#include <sstream> // 字符串流
using namespace std;
int main()
{
string s = "123";
// int i = s; 错误
// string → int
istringstream iss(s);
int i;
iss >> i;
cout << i << endl; // 123
// int → string
// string s2 = i; 错误
stringstream ss;
ss << i;
string s2 = ss.str();
cout << s2 << endl;
return 0;
}
5、函数
5.1 内联函数(掌握)
内联函数用于取代C语言中宏定义的函数,内联函数的正确使用可以提升程序的执行效率。内联函数在编译的时候,直接把函数体展开到主函数中编译,在运行期间可以减少调用的开销。
通常将具有以下性质的函数写为内联函数:
● 代码长度5行以内
● 不包含复杂的控制语句
● 频繁被调用
关键字:inline
#include <iostream>
using namespace std;
// 内联函数
inline void pint_string(string str)
{
cout << str << endl;
}
int main()
{
pint_string("hello world");
return 0;
}
后续学习的成员函数默认都添加inline修饰。
但是我们手动添加上了inline关键字,将函数声明成内联函数。这个不是我们可以决定的。编译器有自己的判断准则,我们只是给编译器提供一个建议,具体是否为内联函数,还是编译器自己决定的。
5.2 函数重载 overload(重点)
C++中允许多个函数使用同一个名称,这种用法就是函数重载。函数重载要求函数名称相同,但是参数不同(类型、数量、前后顺序不同)。与返回值等其他因素无关。
#include <iostream>
using namespace std;
void print_show(int i)
{
cout << "调用了int重载"<< i << endl;
}
void print_show(float i)
{
cout << "调用了float重载"<< i << endl;
}
void print_show(double i)
{
cout << "调用了double重载"<< i << endl;
}
void print_show(string str)
{
cout << "调用了string重载"<< str << endl;
}
void print_show()
{
cout << "调用了无参int重载"<< endl;
}
int main()
{
print_show(1);
return 0;
}
5.3 哑元函数(熟悉)
函数的参数只有类型,没有名称,这样参数的就是哑元函数。
#include <iostream>
using namespace std;
// 哑元函数
void print_show(int)
{
cout << "调用了int的哑元函数" << endl;
}
int main()
{
print_show(56);
return 0;
}
作用一:哑元函数用来区分函数重载。
作用二:运算符重载中用到。
#include <iostream>
using namespace std;
// 哑元函数
void print_show(int i,int)
{
cout << "调用了int的哑元函数" << endl;
}
void print_show(int i)
{
cout << "调用了int的哑元函数"<< i << endl;
}
int main()
{
print_show(56,23);
return 0;
}