Bootstrap

从C到C++

目录

从C到C++

1、  引用(掌握)

1.1 概念

1.2 引用的性质

1.3 引用参数

2、  赋值(熟悉)

3、  键盘输入(熟悉)

4、  string字符串类(掌握)

5、函数

5.1 内联函数(掌握)

5.2 函数重载 overload(重点)

5.3 哑元函数(熟悉)


从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;
}

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;