c++中的常用知识点总结

命名空间

使用命名空间之后,调用代码时可以省去也可以不省去相关的前缀。

cpp 复制代码
#include <iostream>

using namespace std;//使用c++自己的命名空间
int main() {
    int num1 = 10;

    std::cout << "Hello, World!" << std::endl;
    cout<<num1<<endl;
    return 0;
}

自定义命名空间

cpp 复制代码
// 命名空间

#include <iostream>

// 声明std,我们的main函数就可以直接使用里面的成员,不需要使用 std::
using namespace std; // C++自己的命名空间 (C# .net 命名空间)

// 自定义命名空间
namespace derry1 {
    int age = 33;
    char * name = "Derry猛男1";

    void show() {
        cout << "name:" << name << ", age:" << age << endl;
    }

    void action() {
        cout << "derry1 action" << endl;
    }
}

// TODO ------ 命名空间里面重复的函数
// 自定义命名空间
namespace derry2 {
    void action() {
        cout << "derry2 action" << endl;
    }
}

// TODO ------ 小概率会遇到的情况,命名空间的嵌套
// 自定义命名空间
namespace derry3 {
    namespace derry3Inner {
        namespace derry3Inner1 {
            namespace derry3Inner2 {
                namespace derry3Inner3 {
                    void out() {
                        cout << "爱恨情仇人消瘦,悲欢起落人寂寞" << endl;
                    }
                }
            }
        }
    }
}

// 声明各个写的 命名空间
// using namespace derry1;

int main() {
    cout << "命名空间" << endl;

    // 声明各个写的 命名空间
    using namespace derry1;

    int ageValue = derry1::age; // 方式1 使用 刚刚声明的命名空间
    derry1::show(); // 使用 刚刚声明的命名空间

    ageValue = age; // 方式2 直接去引出来 ::
    show(); // 直接去引出来 ::


    // TODO ------ 命名空间里面重复的函数
    using namespace derry2;
    // action(); 很尴尬
    derry1::action();
    derry2::action();

    // TODO ------ 小概率会遇到的情况,命名空间的嵌套

    // 第一种方式 先声明命名空间  再使用
    using namespace derry3::derry3Inner::derry3Inner1::derry3Inner2::derry3Inner3;
    // 再使用
    out();

    // 第二种方式 直接使用
    derry3::derry3Inner::derry3Inner1::derry3Inner2::derry3Inner3::out();

    return 0;
}

  • 头文件:Student.h
cpp 复制代码
//
// Created by sunteng on 2023/9/5.
//

#ifndef TEST_STUDENT_H
#define TEST_STUDENT_H

#endif //TEST_STUDENT_H

class Student{

private:
    //下面的成员和函数,都是私有
    char * name;
    int age;

public:
    //下面的成员和函数,都是公有
    void setAge(int age);
    void setName(char *name);
    int getAge();
    char * getName();

};
  • 类文件:Student.cpp
cpp 复制代码
//
// Created by sunteng on 2023/9/5.
//


#include "Student.h"

// 根据 Student.h 头文件 ,写实现

// 和实现头文件那个函数,没有任何关系,相当于另外一个函数
/*void setAge(int age) {

}*/

void Student::setAge(int age) {
    //this是一个Student类型的指针
    this->age = age;
}

void Student::setName(char *name) {
    this->name = name;
}

int Student::getAge() {
    return this->age;
}

char * Student::getName() {
    return this->name;
}
  • main
cpp 复制代码
#include <iostream>
#include "Student.h"//引入头文件即可
using namespace std;
int main() {

    Student student1;//栈区开辟空间

    //赋值
    student1.setName("brett");
    student1.setAge(19);

    cout<<"name:"<<student1.getName()<<" ,age:"<<student1.getAge()<<endl;

    Student* student2 = new Student();//new 堆区分配空间

    student2->setAge(88);
    student2->setName("mike");

    cout<<"name:"<<student2->getName()<<" ,age:"<<student2->getAge()<<endl;


    //堆区分配的对象使用完之后必须手动释放
    if(student2){
        delete student2;
        student2 = NULL;
    }
    // new/delete 是一套  会调用构造函数 与 析构函数   【C++标准规范】
    // malloc/free是一套  不调用构造函数 与 析构函数 【C的范畴,虽然不推荐,但是也是可以的】


    return 0;
}
  • 构造函数和析构函数
cpp 复制代码
#include <iostream>
#include <string.h>
using namespace std;

class Student {

// 构造函数
public:
    // 空参数构造函数
    Student() {
        cout << "空参数构造函数" << endl;
    }

    // 一个参数的构造函数
    // :Student(name, 87) 等价 1.调用两个参数的构造函数, 2.再调用当前函数
    // 学生说的:先调用两个参数的,再调用一个的
    Student(char *name) :Student(name, 87) {
        cout << "一个参数的构造函数" << endl;
        if(!this->name){//防止重复赋值
            this->name = name;
        }

    }

    // 两个参数的构造函数
    Student(char *name, int age) {
        // this->name = name;

        // 堆区
        this->name = (char *) (malloc(sizeof(char *) * 10));
        strcpy(this->name, name);

        this->age = age;
        cout << "两个参数的构造函数" << endl;
    }

    // 析构函数 Student对象的,临终遗言,Student对象被回收了,你做一些释放工作
    // delete stu 的时候,我们的析构函数一定执行
    // free不会执行析构函数,也意味着,你没法在析构函数里面,做释放工作, malloc也不会调用构造函数
    ~Student() {
        cout << "析构函数" << endl;

        // 必须释放 堆区开辟的成员
        if (this->name) {
            free(this->name);
            this->name = NULL; // 执行NULL的地址,避免出现悬空指针
        }
    }

// 私有属性
private:
    char *name;
    int age;

// 公开的 set get 函数
public:
    int getAge() {
        return this->age;
    }

    char *getName() {
        return this->name;
    }

    void setAge(int age) {
        this->age = age;
    }

    void setName(char *name) {
        this->name = name;
    }
};

int main() {


    // TODO =========== 下面是堆区 开辟空间的  堆区必须手动释放,否则内存占用越来

    // 系统源码中,会看到,很多使用 new 关键字

    // *stu  ->:调用一级指针的成员
    // new/delete
    // C++中,必须使用 new/delete 一套
    Student *stu = new Student("杜子腾");
    cout << "name:" << stu->getName() << ", age:" << stu->getAge() <<  endl;
    delete stu;


    return 0;
}
  • 拷贝构造函数与构造函数
cpp 复制代码
// 4.拷贝构造函数。

#include <iostream>
#include <string.h>

using namespace std;

class Student {

public:
    Student() { cout << "空参数构造函数" << endl; }

    // 两个参数的构造函数
    Student(char *name, int age) : name(name), age(age) {
        cout << "两个参数构造函数" << endl;
    }

    // 析构函数
    // ~Student(char * name) { } 这样写,就不是析构函数了,如果你这样写,C/C++编译器对你很无语
    ~Student() {
        cout << "析构函数" << endl;
    }

    // 拷贝构造函数,它默认有,我们看不到,一旦我们写拷贝构造函数,会覆盖她
    // 对象1 = 对象2
    // 覆盖拷贝构造函数
    Student(const Student & student) { // 常量引用:只读的,不让你修改
        cout << "拷贝构造函数" << endl;

        // 我们自己赋值
        // 为什么要自己赋值,自己来控制,就可以 例如:-10
        this->name = student.name;
        this->age = student.age - 10;

        cout << "自定义拷贝构造函数 内存地址 " << &student << endl;
    }

// 私有属性
private:
    char *name;
    int age;

// 公开的 set get 函数
public:
    int getAge() {
        return this->age;
    }

    char *getName() {
        return this->name;
    }

    void setAge(int age) {
        this->age = age;
    }

    void setName(char *name) {
        this->name = name;
    }
};

struct Person {
    int age;
    char *name;
};

// TODO = 号的意义 隐士代码,引出 拷贝构造函数

int main() {
    Person person1 = {100, "张三丰"};

    // = 你看起来,没有什么特殊,隐士的代码:你看不到  C/C++编译器 会把p1的成员值赋值给p2成员
    Person person2 = person1;

    cout << &person1 << endl;
    cout << &person2 << endl;

    cout << person2.name << ",  " << person2.age << endl;

    // 思考:对象 对象1=对象2  默认的 拷贝构造函数

    return 0;
}

// TODO  拷贝构造函数

/*int main() {
    Student stu1("李鬼", 34);
    Student stu2 = stu1;

    cout << stu2.getName() << " , " <<  stu2.getAge() <<  endl;
    cout << "main " << &stu1 << endl; // 地址的打印是一样的,  注意:cnetos的环境 地址打印有差异,要注意



    // TODO  拷贝构造函数的注意点:
    // Student stu1("李鬼", 34);

    // Student stu2;
    // stu2 = stu1; // 这样赋值是不会调用 自定义拷贝构造函数,但是会调用默认赋值
    // Student stu2 = stu1;  // 这样赋值是会调用 自定义拷贝构造函数,我们自己赋值

    // cout << stu2.getName() << " , " <<  stu2.getAge() <<  endl;

    getchar(); // 程序等待在这一行

    return 0;
} // main函数弹,stu1栈成员会回收  stu2栈成员会回收
*/

// TODO 这种写法 拷贝构造函数  到底会不会调用
/*int main() {
    Student *student1 = new Student("杜子腾", 39);

    Student *student2 = student1;  // 压根就不会执行拷贝构造函数(指针指向问题,和我们刚刚那个  对象2=对象1 是两回事)

    student2->setAge(99);

    cout << student1->getName() << student1->getAge() << endl;

    return 0;
}*/
  • 深拷贝与浅拷贝
cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS // strcpy运行会报错,支持

#include<iostream>
#include<string.h>
using namespace std;

class Student
{
public:

    int age;
    char * name;

    Student() { cout << "空参数构造函数" << endl; }

    Student(char * name) :Student(name, 99) {
        cout << "一个参数构造函数 this:" << this << endl;
    }

    Student(char * name, int age) {
        cout << "二个参数构造函数 this:" << this << endl;

        this->name = (char *)malloc(sizeof(char *)* 10);
        strcpy(this->name, name);

        this->age = age;
    }

    ~Student() {
        cout << "析构函数执行 &this->name:" << this->name << endl;

        free(this->name);
        this->name = NULL;
    }

    // 默认有一个拷贝构造函数 隐士的 我们看不见
    // 一旦复写了拷贝构造函数,默认的还在吗? Java的构造函数一个思路
    // 自定义拷贝构造函数 如果有堆成员,必须采用深拷贝
    Student(const Student & stu) {
        // stu 旧地址

        // this 新地址

        // s2 = 新地址

        cout << "拷贝构造函数 &stu:" << &stu << " this:" << this << endl;//二者地址不一样

        // 【浅拷贝】:新地址name  旧地址name 指向同一个空间,会造成,重复free的问题,引发奔溃
        // 新地址name = 旧地址 (浅拷贝)
        // this->name = stu.name;

        // 【深拷贝】
        this->name = (char *)malloc(sizeof(char *)* 10);
        strcpy(this->name, name);

        this->age = stu.age;

        cout << "拷贝构造函数2 this->name:" << (this->name) << "  stu.name:" << stu.name << endl;

        // 深拷贝 后面见  原理全部打通的时候讲
    } // 此拷贝构造函数执行完 旧会出现一个 this==新地址  给 main函数的 stu


    // 默认的拷贝构造函数 是浅拷贝
};

void showStudent(Student stu) {
    cout << "showStudent函数:" << &stu << "  " << stu.name << "," << stu.age<< endl;
}

int main() {
    Student stu("刘奋", 31);

    showStudent(stu); // 弹栈后 新地址name释放一遍
    showStudent(stu);
//
//    showStudent(stu);
//
//
//    showStudent(stu);
//
//
//    showStudent(stu);

    getchar();
    return 0;
} // main函数弹栈 stu 旧地址

指针常量 常量指针 常量指针常量

cpp 复制代码
// 指针常量 常量指针 常量指针常量

#include <iostream>
#include <string.h>
#include <string.h>

using namespace std;

int main() {

    // *strcpy (char *__restrict, const char *__restrict);
    // strcpy()


    int number = 9;
    int number2 = 8;

    // 大道至简 一分钟搞定

    // 常量指针
    const int * numberP1 = &number;
    // *numberP1 = 100; // 报错,不允许去修改【常量指针】存放地址所对应的值
    // numberP1 = &number2; // OK,允许重新指向【常量指针】存放的地址

    //  指针常量
    int* const numberP2 = &number;
    *numberP2 = 100; // OK,允许去修改【指针常量】存放地址所对应的值
    // numberP2 = &number2; // 报错,不允许重新指向【指针常量】存放的地址

    // 常量指针常量
    const int * const numberP3 = &number;
    // *numberP3 = 100; // 报错,不允许去修改【常量指针常量】存放地址所对应的值
    // numberP3 = &number2; // 报错,不允许重新指向【常量指针常量】存放的地址

    return 0;
}

运算符重载

cpp 复制代码
// 2.类里运算符重载。

#include <iostream>
using namespace std;

class Derry {
private:
    int x,y;

public:
    Derry() {

    }

    // 系统C++源码,大量使用此方式 :x(x), y(y)
    Derry(int x, int y) :x(x), y(y) {}

    // set get 函数
    void setX(int x) {
        this->x = x;
    }
    void setY(int y) {
        this->y = y;
    }
    int getX() {
        // this->x  -9; 系统怕你在函数里面 修改了
        return this->x;
    }
    int getY() {
        return this->y;
    }

    // +号,运算符重载
    /*Derry operator + (Derry derry1) {
        // this指针 指向当前对象,所以只需要一个
        int x = this->x + derry1.getX();
        int y = this->y + derry1.getY();
        return Derry(x, y);
    }*/

    // 系统是这样写的  常量引用:不允许修改,只读模式
    // const 关键字的解释
    // & 性能的提高,如果没有&  运行+ 构建新的副本,会浪费性能
    // 如果增加了& 引用是给这块内存空间取一个别名而已
    Derry operator + (const Derry& derry1) {
        // this指针 指向当前对象,所以只需要一个
        int x = this->x + derry1.x; // 我在类的里面,是可以拿私有成员的
        int y = this->y + derry1.y; // 我在类的里面,是可以拿私有成员的
        return Derry(x, y);
    }

    // 运算符- 重载
    Derry operator - (const Derry & derry1) {
        int x = this->x - derry1.x;
        int y = this->y - derry1.y;
        return Derry(x, y);
    }
};

int main() {
    Derry derry1(1000, 2000);
    Derry derry2(3000, 4000);

    // Derry result = derry1 + derry2;

     Derry result = derry2 - derry1;

    cout << result.getX() << " , " << result.getY() << endl;

    return 0;
}

二义性与虚基类

cpp 复制代码
// 多继承 二义性2:
// 在真实开发过程中,严格避免出现 二义性

#include <iostream>

using namespace std;

// 祖父类
class Object {
public:
    int number;
};

// 父类1
class BaseActivity1 : public Object {

};

// 父类2
class BaseActivity2 : public Object {

};

// 子类
class Son : public BaseActivity1, public BaseActivity2 {

    // 第二种解决方案: 在类中定义同名成员,覆盖掉父类的相关成员
public:
    int number;

};


int main() {
    Son son;

    // error: request for member 'show' is ambiguous  二义性 歧义
    // son.number = 2000;

    // 第一种解决方案: :: 明确指定
    son.BaseActivity1::number  = 1000;
    son.BaseActivity2::number  = 1000;

    // 第二种解决方案: 在类中定义同名成员,覆盖掉父类的相关成员
    son.number = 3000;

    // 第三种解决方案: 【虚基类】 属于 虚继承的范畴

    return 0;
}

//第三种方式;虚基类

// 第三种解决方案: 【虚基类】 属于 虚继承的范畴
// 真实C++开始,是很少出现,二义性(歧义) 如果出现, 系统源码(系统用 第三种解决方案)

#include <iostream>

using namespace std;

// 祖父类
class Object{
public:
    int number;
    void show() {
        cout << "Object show run..." << endl;
    }
};

// 父类1
class BaseActivity1 : virtual public Object {
};

// 父类2
class BaseActivity2 : virtual public Object {
};

// 子类
class Son : public BaseActivity1, public BaseActivity2 {

};

int main() {
    Object object;
    BaseActivity1 baseActivity1;
    BaseActivity2 baseActivity2;
    Son son;

    object.number = 100;
    baseActivity1.number = 200;
    baseActivity2.number = 300;
    son.number = 400;

    object.show();
    baseActivity1.show();
    baseActivity2.show();
    son.show();

    cout << object.number << endl;
    cout << baseActivity1.number << endl;
    cout << baseActivity2.number << endl;
    cout << son.number << endl;

    return 0;
}
  • 虚基类

在C++中,虚基类是用于解决多继承中的菱形继承问题的一种机制。菱形继承指的是一个派生类同时继承自两个或多个基类,而这些基类又共同继承自同一个基类,形成了一个菱形的继承结构。

虚基类的作用是解决菱形继承带来的二义性和冗余的问题。当一个派生类通过多条路径继承自同一个基类时,如果不使用虚基类,那么在派生类中就会存在多个基类子对象的实例,这样就会导致同名成员在派生类中出现冗余,访问这些成员时会产生二义性。

通过使用虚基类,可以确保在派生类中只有一个基类子对象的实例,从而避免了冗余和二义性。虚基类的成员在派生类中只有一份拷贝,这样就可以确保派生类对基类成员的访问是唯一的。

使用虚基类的语法是在派生类的基类列表中,将虚基类声明为虚基类。例如:

cpp 复制代码
class Base {
public:
    // Base类的成员
};

class Derived1 : virtual public Base {
public:
    // Derived1类的成员
};

class Derived2 : virtual public Base {
public:
    // Derived2类的成员
};

class Derived3 : public Derived1, public Derived2 {
public:
    // Derived3类的成员
};

在上面的例子中,Base是虚基类,Derived1和Derived2都通过虚继承方式继承自Base。Derived3通过多继承同时继承自Derived1和Derived2,这样就避免了菱形继承带来的问题。

总结来说,虚基类的作用是解决多继承中的菱形继承问题,避免冗余和二义性,确保派生类对基类成员的访问是唯一的。

公有继承与私有继承

cpp 复制代码
#include <iostream>

using namespace std;

class Person {
public:
    char *name;
    int age;

public:
    Person(char *name, int age) : name(name) {
        this->age = age;
        cout << "Person 构造函数" << endl;
    }

    void print() {
        cout << this->name << " , " << this->age << endl;
    }
};

// 1.默认是 隐式代码: : private Person
// 2.私有继承:在子类里面是可以访问父类的成员,但是在类的外面不行
// 3.必须公开继承,才可以访问父类的成员
class Student : public Person {

// 类 默认是私有,注意下

private:
    char * course;

public:
    // :父类 , 给自己子类成员初始化
    Student(char * name, int age, char* course) : Person(name, age) , course(course) {
        cout << "Student 构造函数" << endl;
    }

    void test() {
        cout << name << endl;
        cout << age << endl;
        print();
    }
};

int main() {
    Student stu("李元霸", 99, "C++");

    // 公开继承,才可以拿父类的成员
    stu.name = "李四";
    return 0;
}

静态类

cpp 复制代码
// 2.C++static关键字。 正确的写法

/**
 * 静态的总结:
 * 1.可以直接通过类名::静态成员(字段/函数)
 * 2.静态的属性必须要初始化,然后再实现(规则)
 * 3.静态的函数只能取操作静态的属性和方法
 */

#include <iostream>

using namespace std;

class Dog {
public:
    char * info;
    int age;

    // 先声明
    static int id;

    static void update() {
        id += 100;

        // 报错:静态函数不能调用非静态函数
        // update2();
    }

    void update2() {
        id = 13;
    }
};

// 再实现
int Dog::id = 9;

int main() {
    Dog dog;
    dog.update2(); // 普通函数
    Dog::update(); // 静态函数
    dog.update(); // 对象名.静态函数(一般都是使用::调用静态成员,这种方式可以 知道就行)

    cout << Dog::id << endl;
    return 0;
}

友元类和友元函数

在C++中,友元类和友元函数是一种特殊的访问权限控制机制,允许一个类或函数访问另一个类的私有成员。

友元类(Friend Class)是指在一个类中声明另一个类为友元,从而使得被声明的类可以访问声明它为友元的类的私有成员。友元类的声明通常出现在类的定义中,例如:

cpp 复制代码
class A {
    friend class B; // B是A的友元类
private:
    int privateData;
};

class B {
public:
    void accessPrivateData(A& obj) {
        int data = obj.privateData; // 可以访问A类的私有成员
    }
};

在上面的例子中,类B被声明为类A的友元类,因此类B可以访问类A的私有成员privateData。

友元函数(Friend Function)是指在一个类中声明一个函数为友元,从而使得被声明的函数可以访问声明它为友元的类的私有成员。友元函数的声明通常出现在类的定义中,例如:

cpp 复制代码
class A {
    friend void printPrivateData(A& obj); // printPrivateData是A的友元函数
private:
    int privateData;
};

void printPrivateData(A& obj) {
    int data = obj.privateData; // 可以访问A类的私有成员
}

在上面的例子中,函数printPrivateData被声明为类A的友元函数,因此函数printPrivateData可以访问类A的私有成员privateData。

需要注意的是,友元类和友元函数破坏了封装性,因此应该谨慎使用。过度使用友元可能会导致代码的可维护性和可读性下降。在设计类的时候,应该优先考虑使用成员函数和访问修饰符(如public、private、protected)来实现对类成员的访问控制。只有在确实需要访问私有成员的特殊情况下,才考虑使用友元类或友元函数。

cpp 复制代码
// 友元函数

// 老外:你是它的好朋友,那就可以拿私有成员给好朋友

#include <iostream>

using namespace std;

class Person {
private: // 私有的age,外界不能访问
    int age = 0;

public:
    Person(int age) {
        this->age = age;
    }

    int getAge() {
        return this->age;
    }

    // 定义友元函数 (声明,没有实现)
    friend void updateAge(Person * person, int age);
};

// 友元函数的实现,可以访问所以私有成员
void updateAge(Person* person, int age) {
    // 默认情况下:不能修改 私有的age
    // 谁有这个权限:友元(拿到所有私有成员)
    person->age = age;
}

int main() {
    Person person = Person(9);
    updateAge(&person, 88);

    cout << person.getAge() << endl;
    return 0;
}

可变参数

cpp 复制代码
#include <iostream>
#include <stdarg.h> // 可变参数的支持
using namespace std;

// Java的可变参数: int ...
// C++的可变参数写法:...

// count变量的第二个用处,用于循环遍历长度
void sum(int count, ...) {
    va_list vp; // 可变参数的动作

    // 参数一:可变参数开始的动作vp
    // 参数二:内部需要一个 存储地址用的参考值,如果没有第二个参数,内部他无法处理存放参数信息
    va_start(vp, count);

    // 到这里后:vp就已经有丰富的信息

    for (int i = 0; i < count; ++i) {
        int r = va_arg(vp, int);
        cout << r << endl;
    }

    // 越界 系统值 乱码
    // 取出可变参数的一个值 【娶不到后,会取系统值 乱码】
//   int number  = va_arg(vp, int);
//    cout << number << endl;

    // 关闭阶段(规范:例如:file文件一样 要关闭)
    va_end(vp);
}

// 1.可变参数
int main() {

    sum(3, 6,7,8); // 真实开发过程的写法

    return 0;
}

this是什么------指针常量

cpp 复制代码
class Worker {
public:
    char * name;
    int age = NULL; // C++中不像Java,Java有默认值, 如果你不给默认值,那么就是系统值 -64664

    // int * const  指针常量 指针常量【地址对应的值能改,地址不可以修改】
    // const int *  常量指针 常量指针【地址可以修改,地址对应的值不能改】

    // 纠结:原理:为什么可以修改age
    // 默认持有隐士的this【类型 * const this】
    // 类型 * const 指针常量:代表指针地址不能被修改,但是指针地址的值是可以修改的
    void change1() {
        // 代表指针地址不能被修改
        // this = 0x6546;  // 编译不通过,地址不能被修改,因为是指针常量
        // 地址不可以修改
        // this = 0x43563;

        // 隐士的this
        // 但是指针地址的值是可以修改的
        // 地址对应的值能改
        this->age = 100;
        this->name = "JJJ";
    }

    // 默认现在:this 等价于 const Student * const  常量指针常量(地址不能改,地址对应的值不能改)
    void changeAction() const {
        // 地址不能改
        // this = 0x43563;

        // 地址对应的值不能改
        // this->age = 100;
    }

    // 原理:修改隐士代码  const 类型 * const 常量指针常量
    void showInfo() const {
        // this->name = "";
        // this->age = 88;

        // 只读的
        cout << "age:" << age << endl;
    }
};

多线程

C++ 11 之后添加了新的标准线程库 std::thread,std::thread 在 头文件中声明,因此使用 std::thread 时需要包含 在 头文件。

cpp 复制代码
// 演示多线程的CPP程序
// 使用三个不同的可调用对象
#include <iostream>
#include <thread>
using namespace std;

// 一个虚拟函数
void foo(int Z)
{
      for (int i = 0; i < Z; i++) {
            cout << "线程使用函数指针作为可调用参数\n";
          }
}

// 可调用对象
class thread_obj {
public:
      void operator()(int x)
      {
            for (int i = 0; i < x; i++)
              cout << "线程使用函数对象作为可调用参数\n";
          }
};

int main()
{
      cout << "线程 1 、2 、3 "
        "独立运行" << endl;
    
      // 函数指针
      thread th1(foo, 3);//不需要显式调用start()方法来启动线程,std::thread对象的构造函数会自动启动线程的执行。
    
      // 函数对象
      thread th2(thread_obj(), 3);
    
      // 定义 Lambda 表达式
      auto f = [](int x) {
            for (int i = 0; i < x; i++)
              cout << "线程使用 lambda 表达式作为可调用参数\n";
          };
    
      // 线程通过使用 lambda 表达式作为可调用的参数
      thread th3(f, 3);
    
      // 等待线程完成
      // 等待线程 t1 完成
      th1.join();
    
      // 等待线程 t2 完成
      th2.join();
    
      // 等待线程 t3 完成
      th3.join();
    
      return 0;
}

/*
线程 1 、2 、3 独立运行
线程使用函数指针作为可调用参数
线程使用函数指针作为可调用参数
线程使用函数指针作为可调用参数
线程使用函数对象作为可调用参数
线程使用函数对象作为可调用参数
线程使用函数对象作为可调用参数
线程使用 lambda 表达式作为可调用参数
线程使用 lambda 表达式作为可调用参数
线程使用 lambda 表达式作为可调用参数
*/
相关推荐
郑州光合科技余经理7 分钟前
海外国际版同城服务系统开发:PHP技术栈
java·大数据·开发语言·前端·人工智能·架构·php
跨境卫士苏苏8 分钟前
突围新品广告泥潭:亚马逊广告底层逻辑大重构
大数据·人工智能·算法·重构·亚马逊·防关联
Yorelee.9 分钟前
ms-swift在训练时遇到的部分问题及解决方案
开发语言·nlp·transformer·swift
行走的bug...12 分钟前
python项目管理
开发语言·python
CryptoRzz26 分钟前
日本股票 API 对接实战指南(实时行情与 IPO 专题)
java·开发语言·python·区块链·maven
yugi98783827 分钟前
基于M序列的直扩信号扩频码生成方法及周期长码直扩信号的MATLAB实现方案
开发语言·matlab
旧梦吟32 分钟前
脚本网页 三人四字棋
前端·数据库·算法·css3·html5
乾元34 分钟前
基于时序数据的异常预测——短期容量与拥塞的提前感知
运维·开发语言·网络·人工智能·python·自动化·运维开发
江上清风山间明月35 分钟前
使用python将markdown文件生成pdf文件
开发语言·python·pdf
凯_kyle35 分钟前
Python 算法竞赛 —— 基础篇(更新ing)
笔记·python·算法