【c++随笔03】构造函数、析构函数、拷贝构造函数、移动构造函数

news2024/11/25 18:36:41

【c++随笔03】构造函数、析构函数、拷贝构造函数、移动构造函数

  • 一、构造函数
    • 1、为何要有构造函数?
    • 2、构造函数定义
    • 3、无参构造、带参构造
    • 4、构造函数注意事项
      • 4.1 构造函数是特殊的,不是常规的成员函数,不能直接调d1.Date() 。
      • 4.2 如果通过无参构造函数创建对象,对象后面不用跟括号,否则就成了函数声明。
      • 4.3 这里如果调用带参构造函数,我们需要传递三个参数(这里我们没设缺省) 。
      • 4.4 如果你没有自己定义构造函数(类中未显式定义),C++ 编译器会自动生成一个无参的默认构造函数。当然,如果你自己定义了,编译器就不会帮你生成了。
      • 4.5 默认构造函数:包括无参构造函数、全缺省构造函数
      • 4.6 任何一个类的默认构造函数,只有三种:
  • 二、析构函数
    • 1、概念
    • 2、demo
    • 3、编译器自动生成的析构函数
  • 三、拷贝构造函数、拷贝赋值运算符
    • 1、为何要有拷贝构造函数
    • 2、拷贝构造函数特点
    • 3、demo(拷贝构造函数、拷贝赋值运算符)
    • 4、浅拷贝、深拷贝
    • 5、浅拷贝
    • 6、深拷贝
  • 四、移动构造函数、移动构造赋值运算符
    • 1、概念
    • 2、定义
    • 3、demo(移动构造函数、移动构造赋值运算符)
    • 4、noexcept

一、构造函数

1、为何要有构造函数?

我们先看一段代码

#include <iostream>

class Date {
public:
    void setDate(int year, int month, int day) 
    {
        m_year = year;
        m_month = month;
        m_day = day;
    }
    void print() 
    {
        printf("%d-%d-%d\n", m_year, m_month, m_day);
    }

private:
    int m_year;
    int m_month;
    int m_day;
};

int main(void)
{
    Date d1;
    d1.setDate(2022, 3, 8);
    d1.print();
    
    return 0;
}

问题:每次创建Date类的对象d1,可以通过setDate函数设置对象d1每个成员的值,但是每创建一个对象,都通过成员函数setDate来给对象d1赋值,是不是有些麻烦?

  • 是否可以在创建对象d1时就给每个成员赋值呢?
    答案:可以,通过构造函数。

2、构造函数定义

构造函数的概念

  • 构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用。

  • 能够保证每个数据成员都有一个合适的初始值,并且在对象的生命周期内只调用一次。

构造函数的意义:

  • 能够保证对象被初始化。
  • 构造函数是特殊的成员函数,主要任务是初始化,而不是开空间。(虽然构造函数的名字叫构造)

构造函数的特性,构造函数是特殊的成员函数,主要特征如下:

  • 构造函数的函数名和类名是相同的
  • 构造函数无返回值
  • 构造函数可以重载
  • 会在对象实例化时自动调用对象定义出来。

3、无参构造、带参构造

不给参数时就会调用无参构造函数,给参数则会调用带参构造函数。

#include <iostream>

class Date {
public:
    /* 无参构造函数 */
    Date() {
        m_year = 0;
        m_month = 1;
        m_day = 1;
    }
    /* 带参构造函数 */
    Date(int year, int month, int day) {
        m_year = year;
        m_month = month;
        m_day = day;
    }
    void print() 
    {
        printf("%d-%d-%d\n", m_year, m_month, m_day);
    }

private:
    int m_year;
    int m_month;
    int m_day;
};

int main(void)
{
    Date d1;   // 对象实例化,此时触发构造,调用无参构造函数
    d1.print();

    Date d2(2022, 3, 9);   // 对象实例化,此时触发构造,调用带参构造函数
    d2.print();

    return 0;
}

输出

0-1-1
2022-3-9

4、构造函数注意事项

4.1 构造函数是特殊的,不是常规的成员函数,不能直接调d1.Date() 。

	Date d1;
    d1.Date(); // 不能这么去调,构造函数是特殊的,不是常规的成员函数!

4.2 如果通过无参构造函数创建对象,对象后面不用跟括号,否则就成了函数声明。

	Date d2(2022, 3, 9); //正确
    Date d3();  //错误

4.3 这里如果调用带参构造函数,我们需要传递三个参数(这里我们没设缺省) 。

Date d2(2022, 3, 9);   // 正确:对象实例化,此时触发构造,调用带参构造函数
Date d3(2022, 3) //错误,需要传递三个参数(这里我们没设缺省) 。

4.4 如果你没有自己定义构造函数(类中未显式定义),C++ 编译器会自动生成一个无参的默认构造函数。当然,如果你自己定义了,编译器就不会帮你生成了。

#include <iostream>
class Date {
public:
    void print() {
        printf("%d-%d-%d\n", m_year, m_month, m_day);
    }
private:
    int m_year;
    int m_month;
    int m_day;
};

int main(void)
{
    Date d1;   // 对象实例化,此时触发构造,调用无参构造函数
    d1.print();

    return 0;
}

输出

-858993460–858993460–858993460

4.5 默认构造函数:包括无参构造函数、全缺省构造函数

  • 无参构造函数、
  • 全缺省构造函数

无参的构造函数和全缺省的构造函数都成为默认构造函数,并且默认构造参数只能有一个,语法上他们两个可以同时存在,但是如果有对象定义去调用就会报错。

#include <iostream>

class Date {
public:
    // 无参的构造函数
    Date() {
        m_year = 1970;
        m_month = 1;
        m_day = 1;
    }
    // 全缺省的构造函数
    Date(int year = 1970, int month = 1, int day = 1) {
        m_year = year;
        m_month = month;
        m_day = day;
    }
    void print() 
    {
        printf("%d-%d-%d\n", m_year, m_month, m_day);
    }

private:
    int m_year;
    int m_month;
    int m_day;
};

int main(void)
{
    Date d1;   
    // 无参的构造函数和全缺省的构造函数都成为默认构造函数,并且默认构造参数只能有一个,
    // 语法上他们两个可以同时存在,但是如果有对象定义去调用就会报错。

    return 0;
}

4.6 任何一个类的默认构造函数,只有三种:

  • 无参的构造函数

  • 全缺省的构造函数

  • 我们不写,编译器自己生成的构造函数

C++ 规定:

  1. 我们不写编译器默认生成构造函数,对于内置类型的成员变量,不做初始化处理。
  2. 但是对于自定义类型的成员变量会去调用它的默认构造函数(不用参数就可以调的)初始化。
  3. 如果没有默认构造函数(不用参数就可以调用的构造函数)就会报错!
#include <iostream>
using namespace std;
class A {
public:
    // 如果没有默认的构造函数,会报错。
    A(int a) {    // 故意给个参
        cout << " A() " << endl;
        _a = 0;
    }
private:
    int _a;
};

class Date {
public:
    
    void print() 
    {
        printf("%d-%d-%d\n", m_year, m_month, m_day);
    }

private:
    int m_year;
    int m_month;
    int m_day;
    A m_a;
};

int main(void)
{
    Date d1;   // 无参的构造函数和全缺省的构造函数都成为默认构造函数,并且默认构造参数只能有一个,语法上他们两个可以同时存在,但是如果有对象定义去调用就会报错。

    return 0;
}

报错如下
在这里插入图片描述

从报错可知:当调用Date的默认构造函数时,会自动调用A的构造函数,但是由于A定义了构造函数,所以A就没有默认的构造函数(准确说是,编译器没有给A准备默认构造函数)

把上面A的构造函数删除就可以正常执行了,因为A不写构造函数,编译器就会给准备一个默认的构造函数,不带参数的默认构造函数。

二、析构函数

1、概念

  • 概念:对象在销毁时会自动调用析构函数,完成对象的一些资源清理工作。

构造函数是特殊的成员函数,主要特征如下:

  • 析构函数名是在类名前面加上字符
  • 析构函数既没有参数也没有返回值(因为没有参数,所以也不会构成重载问题)
  • 一个类的析构函数有且仅有一个(如果不写系统会默认生成一个析构函数)
  • 析构函数在对象生命周期结束后,会自动调用。

2、demo

#include <iostream>
using namespace std;
class Date {
public:
    // 全缺省的构造函数
    Date(int year = 1970, int month = 1, int day = 1) {
        m_year = new int(year);
        m_month = month;
        m_day = day;
    }

    // 拷贝构造函数 //以下两种拷贝构造函数写法的效果相同
    ~Date()
    {
        if (nullptr != m_year)
        {
            m_year = nullptr;
            delete m_year;
            cout << "调用了 析构函数" << endl;
        }
    }

    void print() {
        printf("%d-%d-%d\n", *m_year, m_month, m_day);
        // cout << "m_year地址 = " << m_year << endl;
    }

private:
    int *m_year;
    int m_month;
    int m_day;
};

int main(void)
{
    Date d1(2023);
    Date d2(d1); // 调用拷贝构造函数
    d2.print();

    Date d3;
    d3 = d1; // 调用拷贝赋值运算符
    d3.print();

    return 0;
}

输出如下

2023-1-1
2023-1-1
调用了 析构函数
调用了 析构函数
调用了 析构函数

3、编译器自动生成的析构函数

如果不自己写构造函数,让编译器自动生成,那么这个自动生成的 默认构造函数:

  1. 对于 “内置类型” 的成员变量:不会做初始化处理。
  2. 对于 “自定义类型” 的成员变量:会调用它的默认构造函数(不用参数就可以调的)初始化,如果没有默认构造函数(不用参数就可以调用的构造函数)就会报错!
    而我们的析构函数也是这样的,一个德行!

如果我们不自己写析构函数,让编译器自动生成,那么这个 默认析构函数:

  • 对于 “内置类型” 的成员变量:不作处理 (不会帮你清理的.)
  • 对于 “自定义类型” 的成员变量:会调用它对应的析构函数 (已经仁至义尽了) 。

三、拷贝构造函数、拷贝赋值运算符

1、为何要有拷贝构造函数

	Date d1(2023);
    Date d2(d1); // 调用拷贝构造函数
    d2.print();

    Date d3;
    d3 = d1; // 调用拷贝赋值运算符
    d3.print();
  • 问题:我们在创建对象的时候,能不能创建一个与某一个对象一模一样的新对象呢?
  • 答案:可以,这时我们就可以用拷贝构造函数。

2、拷贝构造函数特点

  • 拷贝构造函数是构造函数的一个重载形式。函数名和类名相同,没有返回值。
  • 拷贝构造函数的参数只有一个,并且必须要使用引用传参!

拷贝构造函数用于使用一个对象初始化另一个对象的时候,系统会默认为我们声明实现一个拷贝构造函数,这种默认的拷贝构造函数为浅拷贝

3、demo(拷贝构造函数、拷贝赋值运算符)

#include <iostream>
using namespace std;
class Date {
public:
    // 全缺省的构造函数
    Date(int year = 1970, int month = 1, int day = 1) {
        m_year = year;
        m_month = month;
        m_day = day;
    }

    // 拷贝构造函数 //以下两种拷贝构造函数写法的效果相同
   /* Date(const Date& other) :m_year(other.m_year), m_month(other.m_month), m_day(other.m_day)
    {
        cout << "调用了 拷贝构造函数" << endl;
    }*/
    Date(const Date& other) {
        m_year = other.m_year;
        m_month = other.m_month;
        m_day = other.m_day;
        cout << "调用了 拷贝构造函数" << endl;
    }

    // 拷贝赋值运算符
    Date& operator=(const Date& other) {
        if (this != &other) {
            m_year = other.m_year;
            m_month = other.m_month;
            m_day = other.m_day;
        }
        cout << "调用了 拷贝赋值运算符" << endl;
        return *this;
    }

    void print() {
        printf("%d-%d-%d\n", m_year, m_month, m_day);
    }

private:
    int m_year;
    int m_month;
    int m_day;
};

int main(void)
{
    Date d1(2023);
    Date d2(d1); // 调用拷贝构造函数
    d2.print();

    Date d3;
    d3 = d1; // 调用拷贝赋值运算符
    d3.print();

    return 0;
}

输出

调用了 拷贝构造函数
2023-1-1
调用了 拷贝赋值运算符
2023-1-1

4、浅拷贝、深拷贝

浅拷贝(Shallow Copy)是指新对象只复制了原对象的地址,而没有复制实际的数据。简单来说,浅拷贝只是将指针指向了原始数据的存储位置,多个指针指向同一块内存,修改其中一个对象的数据会影响其他对象。

深拷贝(Deep Copy)是指新对象不仅复制了原对象的数据,还复制了数据所在的内存空间。换句话说,深拷贝将重新分配内存并将原始数据复制到新的内存位置。这样每个对象都有自己独立的内存空间,修改一个对象的数据不会影响其他对象。

C++提供的拷贝构造函数只是简单的将成员变量赋值。如果类里有一个指针,并且申请了一个堆空间,那么在使用默认拷贝构造函数时会使得两个对象指向同一个堆空间。重复释放会导致进程崩溃。

5、浅拷贝

#include <iostream>
using namespace std;
class Date {
public:
    // 全缺省的构造函数
    Date(int year = 1970, int month = 1, int day = 1) {
        m_year = new int(year);
        m_month = month;
        m_day = day;
    }

    // 拷贝构造函数 //以下两种拷贝构造函数写法的效果相同
   /* Date(const Date& other) :m_year(other.m_year), m_month(other.m_month), m_day(other.m_day)
    {
        cout << "调用了 拷贝构造函数" << endl;
    }*/
    Date(const Date& other) {
        m_year = other.m_year;
        m_month = other.m_month;
        m_day = other.m_day;
        cout << "调用了 拷贝构造函数" << endl;
    }

    // 拷贝赋值运算符
    Date& operator=(const Date& other) {
        if (this != &other) {
            m_year = other.m_year;
            m_month = other.m_month;
            m_day = other.m_day;
        }
        cout << "调用了 拷贝赋值运算符" << endl;
        return *this;
    }

    void print() {
        printf("%d-%d-%d\n", *m_year, m_month, m_day);
        cout << "m_year地址 = " << m_year << endl;
    }

private:
    int *m_year;
    int m_month;
    int m_day;
};

int main(void)
{
    Date d1(2023);
    Date d2(d1); // 调用拷贝构造函数
    d2.print();

    Date d3;
    d3 = d1; // 调用拷贝赋值运算符
    d3.print();

    return 0;
}

输出,可以看到year的地址相同

调用了 拷贝构造函数
2023-1-1
m_year地址 = 000001C88A4E67E0
调用了 拷贝赋值运算符
2023-1-1
m_year地址 = 000001C88A4E67E0

6、深拷贝

#include <iostream>
using namespace std;
class Date {
public:
    // 全缺省的构造函数
    Date(int year = 1970, int month = 1, int day = 1) {
        m_year = new int(year);
        m_month = month;
        m_day = day;
    }

    // 拷贝构造函数 //以下两种拷贝构造函数写法的效果相同
   /* Date(const Date& other) :m_year(other.m_year), m_month(other.m_month), m_day(other.m_day)
    {
        cout << "调用了 拷贝构造函数" << endl;
    }*/
    Date(const Date& other) {
        m_year = new int(*other.m_year);
        m_month = other.m_month;
        m_day = other.m_day;
        cout << "调用了 拷贝构造函数" << endl;
    }

    // 拷贝赋值运算符
    Date& operator=(const Date& other) {
        if (this != &other) {
            m_year = new int(*other.m_year);
            m_month = other.m_month;
            m_day = other.m_day;
        }
        cout << "调用了 拷贝赋值运算符" << endl;
        return *this;
    }

    void print() {
        printf("%d-%d-%d\n", *m_year, m_month, m_day);
        cout << "m_year地址 = " << m_year << endl;
    }

private:
    int *m_year;
    int m_month;
    int m_day;
};

int main(void)
{
    Date d1(2023);
    Date d2(d1); // 调用拷贝构造函数
    d2.print();

    Date d3;
    d3 = d1; // 调用拷贝赋值运算符
    d3.print();

    return 0;
}

调用了 拷贝构造函数
2023-1-1
m_year地址 = 0000016E1CE96210
调用了 拷贝赋值运算符
2023-1-1
m_year地址 = 0000016E1CE961D0

四、移动构造函数、移动构造赋值运算符

1、概念

当一个函数的参数按值传递时,这就会进行拷贝,而对于我自己定义的类型,我们也需要提供拷贝构造函数。

但是,不得不说,拷贝的代价是昂贵的。

所以,我们需要寻找一个避免不必要拷贝的方法,

  • 移动构造函数和移动赋值运算符是C++11引入的特性,用于支持对临时对象的高效转移语义。它们可以大幅提升对象的构造和赋值性能,特别是当对象包含大量资源需要进行拷贝或赋值操作时。

2、定义

移动构造函数(Move Constructor):
移动构造函数用于从一个临时对象"偷取"资源而不进行深拷贝,从而提高效率。其函数签名如下:

ClassName(ClassName&& other);

在移动构造函数中,other是一个右值引用,表示一个即将被销毁的临时对象。移动构造函数应该将资源(例如指针、文件句柄等)从other转移到新创建的对象中,并将other中的资源置为无效状态。

  • 移动构造函数,可以避免内存的重新分配,——右值引用提供了一个暂时的对象。

3、demo(移动构造函数、移动构造赋值运算符)

#include <iostream>
using namespace std;
class Date {
public:
    // 全缺省的构造函数
    Date(int year = 1970, int month = 1, int day = 1) {
        m_year = new int(year);
        m_month = month;
        m_day = day;
    }

    // 拷贝构造函数 //以下两种拷贝构造函数写法的效果相同
    Date(Date&& other) noexcept {
        if (this != &other) {
            //delete m_year;

            m_year = other.m_year;
            m_month = other.m_month;
            m_day = other.m_day;

            other.m_year = nullptr;
            other.m_month = 0;
            other.m_day = 0;
        }
        cout << "调用了 移动构造函数" << endl;
    }

    // 拷贝赋值运算符
    Date& operator=(Date&& other) noexcept {
        if (this != &other) {
           // delete m_year;

            m_year = other.m_year;
            m_month = other.m_month;
            m_day = other.m_day;

            other.m_year = nullptr;
            other.m_month = 0;
            other.m_day = 0;
        }
        cout << "调用了 移动构赋值算符" << endl;
        return *this;
    }


    ~Date()
    {
        if (nullptr != m_year)
        {
            m_year = nullptr;
            delete m_year;
            cout << "调用了 析构函数" << endl;
        }
    }

    void print() {
        printf("%d-%d-%d\n", *m_year, m_month, m_day);
        // cout << "m_year地址 = " << m_year << endl;
    }

private:
    int *m_year;
    int m_month;
    int m_day;
};

int main(void)
{
    Date d1(2023);
    Date d2(std::move(d1)); // 调用拷贝构造函数
    //d1.print();//会报错的
    d2.print();

    Date d3(2025);
    Date d4 = std::move(d3); // 调用拷贝赋值运算符
    // d3.print(); //会报错的
    d4.print();

    return 0;
}

输出

调用了 移动构造函数
2023-1-1
调用了 移动构造函数
2025-1-1
调用了 析构函数
调用了 析构函数

4、noexcept

对于移动构造函数和移动赋值运算符,通常建议将它们标记为 noexcept。noexcept 是 C++11 引入的异常规格说明符,用于明确指定函数是否可能引发异常。

将移动操作标记为 noexcept 有以下几个好处:

  • 提高性能:当一个函数被标记为 noexcept 时,编译器可以进行一些优化,以提高代码的执行效率。

  • 支持类型的移动语义:std::vector、std::unordered_map 等容器在执行元素的插入、删除等操作时使用移动语义,如果移动操作可能抛出异常,这些容器就无法利用移动操作来提升性能。

  • 资源管理:在资源管理类(如智能指针)中,移动操作通常用于转移资源的所有权。如果移动操作可能抛出异常,可能会导致资源未正确释放,从而引发资源泄漏。

因此,对于移动构造函数和移动赋值运算符,如果能够确保其不会抛出异常,建议将它们标记为 noexcept。例如:

在上述示例中,我们使用 noexcept 关键字将移动构造函数和移动赋值运算符标记为不会抛出异常。

需要注意的是,如果移动操作调用了可能会抛出异常的函数(如动态内存分配函数 new),则这些移动操作不能标记为 noexcept。

总之,将移动构造函数和移动赋值运算符标记为 noexcept 可以提高代码的性能,并且能更好地支持类型的移动语义和资源管理。但请注意在确保移动操作不会引发异常的情况下使用 noexcept。

参考
1、https://blog.csdn.net/weixin_50502862/article/details/123359614
2、https://blog.csdn.net/qq_34799070/article/details/121298249

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/969958.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

R语言数据管理

1.将变量加入列表中 > mydata<-data.frame(x1c(2,3,4,5),x2c(2,5,7,9)) > mydatax1 x2 1 2 2 2 3 5 3 4 7 4 5 9 > sumx<-x1x2 Error: object x1 not found > sumx<-mydata$x1mydata$x2 > sumx [1] 4 8 11 14 > ls() [1] "mydata&…

【Java 基础篇】StringBuilder的魔力:Java字符串处理探究

在Java编程中&#xff0c;字符串是一个常见的数据类型&#xff0c;用于存储文本信息。然而&#xff0c;与字符串相关的操作可能会导致性能问题&#xff0c;因为字符串是不可变的&#xff0c;每次对字符串进行操作都会创建一个新的字符串对象。为了解决这个问题&#xff0c;Java…

RT-Thread I/O设备模型(一)

I/O设备模型 绝大部分的嵌入式系统都包括一些I/O&#xff08;Input/Output&#xff0c;输入/输出&#xff09;设备&#xff0c;例如仪器上的数据显示屏&#xff0c;工业设备上的串口通信、数据采集设备上用于保存数据的 Flash 或 SD 卡&#xff0c;以及网络设备的以太网接口等…

docker 笔记11: Docker容器监控之CAdvisor+InfluxDB+Granfana

1.原生命令 docker stats命令的结果 是什么 2.是什么 容器监控3剑客 CAdvisor监控收集InfluxDB存储数据Granfana展示图表 3.CAdvisor 4.InfluxDB 5.Granfana 6.总结 7.compose容器编排&#xff0c;一套带走 新建目录 7.1新建3件套组合的 docker-compose.yml version: 3.1vo…

如何写出一篇优秀的博客

写一篇优秀的博客需要经过以下几个步骤&#xff1a; 确定博客的主题和目的 首先要确定博客的主题和目的。这可以根据自己的专业领域、兴趣爱好或者行业热点来定。博客的主题应该具有一定的深度&#xff0c;能够吸引读者的关注&#xff0c;同时博客的目的应该明确&#xff0c;是…

基于x86_64 ubuntu22.04的framebuffer编程

文章目录 前言一、framebuffer简介二、framebuffer接口1.framebuffer设备描述信息2.framebuffer访问接口3.查询/设置可更改信息 三、使用步骤 前言 前段时间由于笔记本没有保管好&#xff0c;LCD显示屏压碎了。于是&#xff0c;将笔记本电脑拆开查看LCD型号。在淘宝上下单买了…

【Java 基础篇】玩转 Java String:技巧与实践

在Java编程中&#xff0c;字符串&#xff08;String&#xff09;是一个非常常见的数据类型&#xff0c;用于存储文本信息。无论是处理用户输入、读取文件内容还是与外部系统进行通信&#xff0c;字符串都扮演着重要的角色。本篇博客将深入讨论Java中的字符串&#xff08;String…

双边滤波 Bilateral Filtering

本文是对图像去噪领域经典的双边滤波法的一个简要介绍与总结&#xff0c;论文链接如下&#xff1a; https://users.soe.ucsc.edu/~manduchi/Papers/ICCV98.pdf 1.前言引入 对一副原始灰度图像&#xff0c;我们将它建模为一张二维矩阵u&#xff0c;每个元素称为一个像素pixel&am…

PID串行多闭环控制与并行多闭环控制的优缺点分析和应用比较

导言&#xff1a; 在自动控制领域&#xff0c;PID控制器是一种经典的控制策略&#xff0c;被广泛应用于各种工业和非工业过程。随着控制系统的复杂性增加&#xff0c;PID串行多闭环控制和PID并行多闭环控制成为解决复杂控制问题的重要方法。本文将从优点和缺点的角度对这两种控…

大数据Flink(七十二):SQL窗口的概述和Over Windows

文章目录 SQL窗口的概述和Over Windows 一、窗口的概述

【100天精通Python】Day53:Python 数据分析_NumPy数据操作和分析进阶

目录 1. 广播 2 文件输入和输出 3 随机数生成 4 线性代数操作 5 进阶操作 6 数据分析示例 1. 广播 广播是NumPy中的一种机制&#xff0c;用于在不同形状的数组之间执行元素级操作&#xff0c;使它们具有兼容的形状。广播允许你在不显式复制数据的情况下&#xff0c;对不同…

2022年09月 C/C++(七级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C编程&#xff08;1~8级&#xff09;全部真题・点这里 第1题&#xff1a;二叉树的深度 给定一棵二叉树&#xff0c;求该二叉树的深度 二叉树深度定义&#xff1a;从根结点到叶结点依次经过的结点&#xff08;含根、叶结点&#xff09;形成树的一条路径&#xff0c;最长路径的…

读SQL学习指南(第3版)笔记10_元数据与大数据

1. 元数据 1.1. metadata 1.2. 关于数据的数据 1.3. 数据字典 1.3.1. ⒅与外键关联的数据表/列 1.3.2. ⒄外键列 1.3.3. ⒃外键名 1.3.4. ⒂存储索引的信息 1.3.5. ⒁索引列的排序&#xff08;升序或降序&#xff09; 1.3.6. ⒀已索引的列 1.3.7. ⑿索引类型&#xf…

CSDN的好处

社区交流&#xff1a;CSDN是一个广大的程序员社区&#xff0c;有很多技术大牛和优秀开发者&#xff0c;可以在这里进行技术交流和讨论&#xff0c;获取最新的技术动态和资源。 学习资源&#xff1a;CSDN上有很多高质量的技术文章、教程和视频资源&#xff0c;可以帮助程序员不…

2023-9-3 筛质数

题目链接&#xff1a;筛质数 埃氏筛法 #include <iostream>using namespace std;const int N 1000010;int cnt; bool st[N];bool get_primes(int n) {for(int i 2; i < n; i ){if(!st[i]){cnt ;for(int j i i; j < n; j i) st[j] true;}} }int main() {int …

linux深入理解多进程间通信

1.进程间通信 1.1 进程间通信目的 数据传输&#xff1a;一个进程需要将它的数据发送给另一个进程资源共享&#xff1a;多个进程之间共享同样的资源。通知事件&#xff1a;一个进程需要向另一个或一组进程发送消息&#xff0c;通知它&#xff08;它们&#xff09;发生了某种事件…

AUTOSAR规范与ECU软件开发(实践篇)7.11 MCAL配置验证与代码生成

在配置完所需MCAL模块之后&#xff0c; 就可以进行配置验证与代码生成。MCAL配置工具的工具栏如图7.64所示。 其中&#xff0c; 右起第二个按钮为“Verify selected project”&#xff0c; 点击之后将进行配置验证。 右起第一个按钮为“Generate Code for the currently select…

小小一个设置程序高级感拉满

手动设置 结果如下 代码设置&#xff1a; procedure TForm1.Button1Click(Sender: TObject); begin TStyleManager.TrySetStyle(cbxVclStyles.Text); end;procedure TForm1.FormCreate(Sender: TObject); var StyleName:string; begin for StyleName in TStyleManager.StyleNa…

查询优化器内核剖析之从一个实例看执行计划

学习查询优化器不是我们的目的&#xff0c;而是通过 它&#xff0c;我们掌握 SQL Server 是如何处理我们的 SQL 的&#xff0c;掌握执行计划&#xff0c;掌握为什么产生 I/O 问题&#xff0c; 为什么 CPU 使用老高&#xff0c;为什么你的索引加了不起作用... 如果&#xff0c;…

数学建模--整数规划匈牙利算法的Python实现

目录 1.算法流程简介 2.算法核心代码 3.算法效果展示 1.算法流程简介 #整数规划模型--匈牙利算法求解 """ 整数规划模型及概念&#xff1a;规划问题的数学模型一般由三个因素构成 决策变量 目标函数 约束条件&#xff1b;线性规划即以线性函数为目标函数&a…