C++_day2

目录

[1. 引用 reference(重点)](#1. 引用 reference(重点))

[1.1 基础使用](#1.1 基础使用)

[1.2 特性](#1.2 特性)

[1.3 引用参数](#1.3 引用参数)

[2. C++窄化(了解)](#2. C++窄化(了解))

[3. 输入(熟悉)](#3. 输入(熟悉))

[4. string 字符串类(掌握)](#4. string 字符串类(掌握))

[4.1 基础使用](#4.1 基础使用)

[4.2 取出元素](#4.2 取出元素)

[4.3 字符串与数字转换](#4.3 字符串与数字转换)

[5. 函数](#5. 函数)

[5.1 内联函数 inline(掌握)](#5.1 内联函数 inline(掌握))

[5.2 函数重载 overload(掌握)](#5.2 函数重载 overload(掌握))

[5.3 函数的参数默认(缺省)值(掌握)](#5.3 函数的参数默认(缺省)值(掌握))

[5.4 哑元函数(熟悉)](#5.4 哑元函数(熟悉))


本章主要讲解非面向对象的升级。

1. 引用 reference(重点)

1.1 基础使用

引用就是某个变量或常量的别名,对引用进行操作与操作原变量或常量完全相同。

cpp 复制代码
#include <iostream>

using namespace std;


int main()
{
    int a = 1;
    int& b = a; // b是a的引用
    b++;
    cout << a << " " << b << endl; // 2 2
    cout << &a << " " << &b << endl; // 0x61fe88 0x61fe88

    return 0;
}

1.2 特性

  • 可以改变引用变量的值,但是不能再次成为其他变量的引用。
cpp 复制代码
#include <iostream>

using namespace std;


int main()
{
    int a = 1;
    int& b = a; // b是a的引用
    int c = 8;
    b = c; // 仅仅是赋值,b仍然是a的别名
    cout << a << " " << b << " " << c << endl; // 8 8 8
    cout << &a << endl; // 地址1
    cout << &b << endl; // 地址1
    cout << &c << endl; // 地址2
//    &b = c; 错误
//    int& b = c; 错误

    return 0;
}
  • 声明引用时,必须初始化。
  • 声明引用时,初始化的值不能为NULL。
  • 声明引用时,初始化的值可以是纯数值,但是此时引用需要使用const修饰,表示常引用,不允许修改引用值。
cpp 复制代码
#include <iostream>

using namespace std;


int main()
{
//    int& b = 123; 错误
    const int& b = 123; // 常引用
    cout << b << endl; // 123
//    b++; 错误

    return 0;
}
  • 可以将变量引用的地址赋值给一个指针,此时指针指向的还是原来的变量。
cpp 复制代码
#include <iostream>

using namespace std;


int main()
{
    int a = 1;
    int &b  = a;
    int* c = &b;
    cout << *c << endl; // 1
    cout << c << " " << &a << endl; // 0x61fe84 0x61fe84

    return 0;
}
  • 可以建立指针变量的引用。
cpp 复制代码
#include <iostream>

using namespace std;


int main()
{
    int a = 1;
    int* b = &a;
    int*& c = b; // c是b的引用
    cout << c << " " << b << " " << endl; // 0x61fe88 0x61fe88
    cout << *c << endl; // 1

    return 0;
}
  • 可以使用const修饰引用,表示常引用,此时不允许改变引用的值,但是可以改变原变量。
cpp 复制代码
#include <iostream>

using namespace std;


int main()
{
    int a = 1;
    const int& b = a; // b是a的常引用
//    b++; 错误
    a++;
    cout << b << endl; // 2

    return 0;
}

1.3 引用参数

【思考题】写一个函数,功能为交换两个int变量参数的数值。

cpp 复制代码
#include <iostream>

using namespace std;

/**
 * @brief swap1 错误的交换方式
 */
void swap1(int a,int b)
{
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
    cout << a << endl; // 2
    cout << b << endl; // 1
}

/**
 * @brief swap2 C的交换方式
 * 指针比较复杂繁琐
 */
void swap2(int* a,int* b)
{
    *a = *a ^ *b;
    *b = *a ^ *b;
    *a = *a ^ *b;
}

/**
 * @brief swap3 使用引用参数传递,方便简洁
 */
void swap3(int& a,int& b)
{
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
}


int main()
{
    int a = 1;
    int b = 2;
    swap1(a,b);
    cout << a << endl; // 1
    cout << b << endl; // 2
    swap2(&a,&b);
    cout << a << endl; // 2
    cout << b << endl; // 1
    swap3(a,b);
    cout << a << endl; // 1
    cout << b << endl; // 2

    return 0;
}

使用引用作为函数参数时,不产生副本,可以使参数传递的效率提升,相比指针又更加简洁。

需要注意的是:

引用参数应该在内被const修饰的情况下,尽量使用const修饰,以达到引用参数的安全性。

cpp 复制代码
#include <iostream>

using namespace std;

void show(const int& a,const int& b)
{
    cout << a << endl;
    cout << b << endl;
}


int main()
{
    int a = 1;
    int b = 2;
    show(a,b);
    cout << a << endl;

    return 0;
}

2. C++窄化(了解)

cpp 复制代码
#include <iostream>

using namespace std;

int main()
{
    double a = 123234.8;
    int b = (int)a; // C强制类型转换格式
    int c(a); // C++格式
    cout << b << endl;
    cout << c << endl;
    int d{a}; // C++11格式:可以给出数据窄化警告
    cout << d << endl;

    return 0;
}

3. 输入(熟悉)

在C++中使用cin进行键盘输入,与cout一样支持连续操作。

cpp 复制代码
#include <iostream>

using namespace std;

int main()
{
    int a;
    double b;
    string c; // C++的字符串类型

    cout << "依次输入整型、浮点型与字符串类型:" << endl;
    // 连续输入三个数据,分别给abc三个变量
    cin >> a >> b >> c;
    cout << "您输入的数据是:" << endl;
    cout << a << endl;
    cout << b << endl;
    cout << c << endl;

    return 0;
}

如果想输入空格,可以使用getline函数,可以一次获得一行的数据:

cpp 复制代码
#include <iostream>

using namespace std;

int main()
{
    string s;
    cout << "请输入一行字符串,可以包含空格:" << endl;
    getline(cin,s);
    cout << "您输入的数据是:" << endl;
    cout << s << endl;

    return 0;
}

4. string 字符串类(掌握)

4.1 基础使用

string不是C++本身的基本数据类型,而是在C++标准库std中的一个字符串类。

在使用时需要引入头文件<string>,而不是<string.h>,string用于在绝大多数情况下代替char*,不必担心内存是否足够、字符串长度等问题。

string内部集成的函数可以完成绝大多数情况下字符串的操作。

string支持多种遍历方式:

  • for循环
  • for-each循环(C++11)
  • 迭代器(后面讲)
cpp 复制代码
#include <iostream>

using namespace std;

int main()
{
    string s = "fsdhfjdhsjkf";
    // size和length效果完全相同
    cout << "字符串长度:" << s.size()
         << " " << s.length() << endl;

    cout << "for循环遍历:" << endl;
    for(int i = 0;i<s.size();i++)
    {
        cout << s[i] << " ";
    }

    cout << endl << "for-each遍历:" << endl;
    for(char i:s)
        cout << i << " ";

    return 0;
}

4.2 取出元素

在C++中除了使用[]取出元素外,还可以使用at函数取出元素。

在绝大多数情况下,更推荐使用at函数取出元素,因为at函数更安全,但是[]性能更好。

cpp 复制代码
#include <iostream>

using namespace std;

int main()
{
    string s = "fsdhfjdhsjkf";
    cout  << s[1] << endl; // 's'
    // at函数
    cout << s.at(1) << endl; // 's'

//    cout << s[-100] << endl; // '\0'或乱码
    cout << s.at(-100) << endl; // 检测到越界则终止运行

    cout << "主函数结束" << endl;
    return 0;
}

4.3 字符串与数字转换

转换方式有很多种,在此使用的是字符串流。

整数 → 字符串

cpp 复制代码
#include <iostream>
#include <sstream> // 头文件

using namespace std;

int main()
{
    int i = 2323;
    stringstream ss;
    ss << i;
    string s = ss.str();
    cout << s << endl;

    return 0;
}

字符串 → 整数

cpp 复制代码
#include <iostream>
#include <sstream> // 头文件

using namespace std;

int main()
{
    string s = "12345";
    istringstream iss(s);
    int i;
    iss >> i;
    cout << i << endl;

    return 0;
}

5. 函数

5.1 内联函数 inline(掌握)

在C++中使用内联函数主要是为了取代C语言中宏定义的函数,内联函数在编译时,可以直接展开函数体到主函数中,因此提升了程序执行的效率,消除了普通的额外开销。

建议把代码长度较小(1-5行且不能包含复杂的控制语句)且频繁使用的函数定义为内联函数,内联函数只是给编译器的建议,编译器并不一定采纳。

只要在函数定义处 使用inline关键字修饰函数,就可以把函数设置为内联函数。

cpp 复制代码
#include <iostream>

using namespace std;

/**
 * @brief test 内联函数
 */
inline void test(int a)
{
    cout << "fdfd" << endl;
    cout << ++a << endl;
}

void func(); // 函数声明

inline void func() // 函数定义
{
    cout << "翻江倒海发的" << endl;
    cout << "法国活动经费" << endl;
}

int main()
{
    int a = 1;
    test(a);
    func();

    return 0;
}

需要注意的是,后面要学习的成员函数默认都定义为内联函数。

5.2 函数重载 overload(掌握)

C++中允许同一个函数名称定义多个函数,这就是函数重载。

函数签名是编译器区分不同函数的方式,包括以下几个组成部分:

  • 函数名称
  • 参数数量
  • 参数类型

两个函数的签名不可以相同,即一个函数只有一个独一无二的签名。

当函数签名中函数名称相同,剩余条件不同时(参数数量或参数类型不同),就构成了函数重载。

cpp 复制代码
#include <iostream>

using namespace std;

void test()
{
    cout << "没有参数" << endl;
}

void test(int a)
{
    cout << "一个int参数" << a << endl;
}

void test(int a,int b)
{
    cout << "两个int参数" << a+b << endl;
}

void test(string a,string b)
{
    cout << "两个string参数" << a+b << endl;
}

//int test(string a,string b) 错误
//{
//    cout << "两个string参数" << a+b << endl;
//    return 1;
//}

int main()
{
    test(1,3);
    test(54);
    test();
    test("aa","bb");

    return 0;
}

后面学习的函数中,需要注意的是:构造函数可以重载,但是析构函数不能重载。

5.3 函数的参数默认(缺省)值(掌握)

C++允许给函数的参数设定默认值,调用函数时如果传入参数,传入的参数会覆盖默认值;调用时如果不传递参数,参数使用预设的默认值。

函数的参数默认值既可以在声明处(建议)设定,又可以在定义处设定,但是只能出现一次。

向右(后)原则:如果函数的参数有多个,只要某个参数设定了默认值,其右边(后面)的所有参数都要设定默认值。

cpp 复制代码
#include <iostream>

using namespace std;

void func(int a = 1)
{
    cout << a << endl;
}

void test(int a = 2);

void test(int a)
{
    cout << a << endl;
}

void method(int a,int b = 1,int c = 2)
{
    cout << a << b << c << endl;
}

int main()
{
    func(); // 1
    func(2); // 2
    test(); // 2
    test(1); // 1
    method(6); // 612
    method(6,6);  // 662
    method(6,6,6); // 666

    return 0;
}

尽量不要同时使用函数重载和参数默认值,因为非常容易出现二义性问题。

cpp 复制代码
#include <iostream>

using namespace std;

void method(int a,int b = 1,int c = 2)
{
    cout << "A"  << a << b << c << endl;
}

void method(int a)
{
    cout  << "B" << a << endl;
}

int main()
{
    method(8,8,8); // A888
    method(5,5); // A552
//    method(9); 错误

    return 0;
}

5.4 哑元函数(熟悉)

一个函数的参数只有类型没有名字,这个参数就是哑元。包含哑元的函数就是哑元函数。

cpp 复制代码
#include <iostream>

using namespace std;

void test(int)
{
    cout << "AAA" << endl;
}

int main()
{
//    test(); 错误
    test(34897);

    return 0;
}

哑元函数的实际功能包括但不限于:

  • 在C++的运算符重载中区分重载函数(后面讲)。
  • 保持函数的向前兼容性。

......

相关推荐
凡人的AI工具箱4 分钟前
15分钟学 Go 第 60 天 :综合项目展示 - 构建微服务电商平台(完整示例25000字)
开发语言·后端·微服务·架构·golang
做人不要太理性7 分钟前
【C++】深入哈希表核心:从改造到封装,解锁 unordered_set 与 unordered_map 的终极奥义!
c++·哈希算法·散列表·unordered_map·unordered_set
程序员-King.16 分钟前
2、桥接模式
c++·桥接模式
chnming198720 分钟前
STL关联式容器之map
开发语言·c++
进击的六角龙22 分钟前
深入浅出:使用Python调用API实现智能天气预报
开发语言·python
檀越剑指大厂22 分钟前
【Python系列】浅析 Python 中的字典更新与应用场景
开发语言·python
VertexGeek23 分钟前
Rust学习(八):异常处理和宏编程:
学习·算法·rust
石小石Orz24 分钟前
Three.js + AI:AI 算法生成 3D 萤火虫飞舞效果~
javascript·人工智能·算法
湫ccc30 分钟前
Python简介以及解释器安装(保姆级教学)
开发语言·python
程序伍六七33 分钟前
day16
开发语言·c++