C++中类和对象的细节原理

文章目录

    • 一、C++中的构造函数
    • 二、C++中的析构函数
    • 三、两者的配合与注意事项
    • 四、C++中的静态成员变量
    • 五、C++中的静态成员函数
    • 六、C++中普通成员函数和静态成员函数的区别
    • 七、C++中的const成员变量
    • 八、C++中的const 成员函数
    • 九、C++中构造函数的初始化列表
    • 十、C++中的浅拷贝操作
    • 十一、C++中的深拷贝操作

一、C++中的构造函数

1.构造函数的定义和作用
构造函数是与类同名的特殊函数,在创建类的对象时自动调用,用于对对象进行初始化。

2.构造函数的特点

  • 与类同名:构造函数的名称必须与类名一致。
  • 无返回值:构造函数没有返回值(即使是 void 也不能写)。
  • 自动调用:在对象创建时自动调用,无需显式调用。
  • 支持重载:可以定义多个构造函数,参数列表不同即可(构成重载)。
  • 可以使用初始化列表:常用于初始化 const 数据成员或引用类型成员。

3.构造函数的类型
默认构造函数:无参数的构造函数。

class MyClass {
public:MyClass() { // 默认构造函数std::cout << "Default constructor called!" << std::endl;}
};
MyClass obj; // 自动调用默认构造函数

参数化构造函数:包含参数的构造函数。

class MyClass {
private:int x;
public:MyClass(int val) : x(val) { // 使用初始化列表std::cout << "Parameterized constructor called!" << std::endl;}
};
MyClass obj(10); // 调用参数化构造函数

拷贝构造函数:用于通过同类型对象初始化新对象。

class MyClass {
private:int x;
public:MyClass(int val) : x(val) {}MyClass(const MyClass& other) : x(other.x) { // 拷贝构造函数std::cout << "Copy constructor called!" << std::endl;}
};
MyClass obj1(10);
MyClass obj2 = obj1; // 调用拷贝构造函数

移动构造函数(C++11 引入):用于移动资源而不是复制资源,减少性能开销。

class MyClass {
private:int* data;
public:MyClass(int val) : data(new int(val)) {}MyClass(MyClass&& other) noexcept : data(other.data) { // 移动构造函数other.data = nullptr;std::cout << "Move constructor called!" << std::endl;}~MyClass() { delete data; }
};
MyClass obj1(10);
MyClass obj2 = std::move(obj1); // 调用移动构造函数

二、C++中的析构函数

1.析构函数的定义和作用
析构函数是与类同名并以 ~ 开头的特殊函数,在对象生命周期结束时自动调用,用于释放资源或执行清理操作。

2.析构函数的特点

  • 与类同名并以 ~ 开头。
  • 无参数、无返回值。
  • 自动调用:在对象超出作用域或被显式删除时自动调用。
  • 不能被重载:每个类只能有一个析构函数。
class MyClass {
public:MyClass() { std::cout << "Constructor called!" << std::endl; }~MyClass() { std::cout << "Destructor called!" << std::endl; }
};
int main() {MyClass obj; // 创建对象时调用构造函数
} // 作用域结束时,自动调用析构函数

3.析构函数的常见用途
释放动态内存:

class MyClass {
private:int* data;
public:MyClass(int val) : data(new int(val)) {}~MyClass() {delete data; // 释放动态内存std::cout << "Destructor called and memory freed!" << std::endl;}
};

三、两者的配合与注意事项

构造和析构的匹配:每次调用构造函数分配资源时,析构函数都应该负责释放资源(遵循 RAII 原则)。
虚析构函数:如果类包含虚函数,析构函数也应声明为 virtual,以确保通过基类指针删除派生类对象时,派生类的析构函数能被正确调用。

class Base {
public:virtual ~Base() { std::cout << "Base destructor called!" << std::endl; }
};
class Derived : public Base {
public:~Derived() { std::cout << "Derived destructor called!" << std::endl; }
};
Base* obj = new Derived();
delete obj; // 调用 Derived 和 Base 的析构函数

四、C++中的静态成员变量

静态成员变量是用 static 关键字声明的类成员变量。它是类的公共成员,在类的所有对象之间共享。
静态成员变量的特点:

  • 属于类,而非对象:静态成员变量只占用一份内存,不随对象的创建而分配,也不会随对象的销毁而释放。
  • 共享性:所有类的对象共享同一个静态成员变量。
  • 必须在类外定义并初始化(除非是 constexpr 静态变量)。
  • 存储周期:程序启动时分配内存,程序结束时释放。
  • 访问方式:可以通过对象或类名访问(推荐通过类名访问)。

类中静态成员变量的声明与定义:

#include <iostream>
class MyClass {
public:static int count; // 静态成员变量声明MyClass() {count++; // 每次创建对象时增加计数}
};// 静态成员变量必须在类外定义并初始化
int MyClass::count = 0;int main() {MyClass obj1, obj2, obj3;std::cout << "Total objects created: " << MyClass::count << std::endl;return 0;
}

C++11 引入的 constexpr 允许静态成员变量在类内定义,但必须是常量且编译时可确定值。

#include <iostream>
class MyClass {
public:static constexpr int maxObjects = 10; // 类内定义并初始化
};int main() {std::cout << "Maximum objects allowed: " << MyClass::maxObjects << std::endl;return 0;
}

五、C++中的静态成员函数

静态成员函数是用 static 修饰的类成员函数。它是类级别的行为,与具体对象无关。
静态成员函数的特点:

  • 不依赖对象:可以通过类名直接调用,无需实例化对象。
  • 只能访问静态成员:静态函数不能访问非静态成员变量或调用非静态成员函数。
  • 共享性:静态成员函数在类的所有对象之间共享。
  • 作用域限制:只能访问与类相关的静态数据或静态成员。

静态成员函数的基本用法:

#include <iostream>
class MyClass {
public:static int count; // 静态成员变量static void printCount() { // 静态成员函数std::cout << "Total objects created: " << count << std::endl;}
};int MyClass::count = 0;int main() {MyClass::count = 5; // 直接通过类名访问静态成员变量MyClass::printCount(); // 直接通过类名调用静态成员函数return 0;
}

静态成员函数访问静态变量:

#include <iostream>class MyClass {
private:static int count; // 静态成员变量
public:static void incrementCount() { count++; } // 修改静态成员变量static int getCount() { return count; }   // 获取静态成员变量
};// 静态成员变量定义和初始化
int MyClass::count = 0;int main() {MyClass::incrementCount(); // 调用静态函数MyClass::incrementCount();std::cout << "Count: " << MyClass::getCount() << std::endl;return 0;
}

六、C++中普通成员函数和静态成员函数的区别

在这里插入图片描述

七、C++中的const成员变量

const 成员变量的定义:

  • const 成员变量是类中的常量,其值一旦初始化后便不能更改。
  • const 成员变量通常需要在构造函数的初始化列表中进行初始化。

const 成员变量的特点:

  • 不可更改:一旦初始化,值不可修改。
  • 初始化方式:只能通过构造函数的初始化列表进行初始化,不能在构造函数的主体中赋值。
  • 作用范围:它的作用域与普通成员变量相同,但只能被读取。
#include <iostream>class MyClass {
private:const int value; // const 成员变量
public:// 使用初始化列表对 const 成员变量初始化MyClass(int v) : value(v) {}void printValue() const {std::cout << "Value: " << value << std::endl;}
};int main() {MyClass obj(42);obj.printValue(); // 输出 Value: 42// obj.value = 10; // 错误:无法修改 const 成员变量return 0;
}

八、C++中的const 成员函数

const 成员函数的定义:

  • const 成员函数是一个不会修改类中任何非静态成员变量的函数。
  • 在函数声明或定义后加 const 关键字来修饰该函数。

const 成员函数的特点:

  • 不能修改成员变量:在函数内不能更改任何非 mutable 的成员变量。
  • 只能调用其他 const 成员函数:在 const 成员函数中不能调用非 const 成员函数。
#include <iostream>class MyClass {
private:int value;
public:MyClass(int v) : value(v) {}int getValue() const { // const 成员函数return value;}void setValue(int v) { // 非 const 成员函数value = v;}
};int main() {const MyClass obj(10); // const 对象std::cout << "Value: " << obj.getValue() << std::endl; // 可以调用 const 成员函数// obj.setValue(20); // 错误:const 对象不能调用非 const 成员函数return 0;
}

普通对象也可以调用 const 成员函数,但 const 对象只能调用 const 成员函数。

int main() {MyClass obj(10); // 普通对象std::cout << "Value: " << obj.getValue() << std::endl; // 可以调用 const 成员函数obj.setValue(20); // 可以调用非 const 成员函数std::cout << "Updated Value: " << obj.getValue() << std::endl;return 0;
}

const 成员函数可以调用其他 const 成员函数,但不能调用非 const 成员函数。

#include <iostream>class MyClass {
private:int value;
public:MyClass(int v) : value(v) {}int getValue() const { return value; }void printValue() const {std::cout << "Value: " << getValue() << std::endl; // 调用另一个 const 成员函数}
};int main() {MyClass obj(42);obj.printValue();return 0;
}

如果类的成员变量用 mutable 修饰,则即使在 const 成员函数中也可以修改它。

#include <iostream>class MyClass {
private:mutable int mutableValue; // 可变成员变量
public:MyClass(int v) : mutableValue(v) {}void modifyValue() const {mutableValue++; // 在 const 成员函数中修改 mutable 成员std::cout << "Mutable Value: " << mutableValue << std::endl;}
};int main() {const MyClass obj(10);obj.modifyValue(); // 修改 mutable 成员变量return 0;
}

九、C++中构造函数的初始化列表

C++ 中,构造函数的初始化列表 是一种在对象构造时初始化类成员的方式。它提供了比在构造函数体内赋值更高效和灵活的初始化方式,特别是对于 const 成员、引用类型成员和基类的初始化至关重要。

1.初始化列表的语法
初始化列表紧跟构造函数的声明,使用冒号 : 开始,并列出成员变量或基类的初始化表达式。

class ClassName {
private:int member1;int member2;
public:// 构造函数使用初始化列表ClassName(int a, int b) : member1(a), member2(b) {// 构造函数体}
};

2.初始化列表的特点

效率高:

  • 初始化列表直接调用构造函数或赋值初始化成员变量,避免了默认构造和后续赋值的过程。
  • 对于复杂对象(如类类型成员),这种方式更高效。

适用性强:

  • 可以初始化const 成员变量。
  • 可以初始化引用类型成员变量。
  • 必须用于基类构造函数调用和成员对象的构造。

成员初始化顺序:

  • 成员的初始化顺序与它们在类中声明的顺序一致,而非在初始化列表中的顺序。
  • 建议按照声明顺序书写初始化列表,以避免潜在的错误和混淆。

3.普通成员变量的初始化

#include <iostream>class MyClass {
private:int x;int y;
public:// 使用初始化列表初始化成员变量MyClass(int a, int b) : x(a), y(b) {}void print() {std::cout << "x: " << x << ", y: " << y << std::endl;}
};int main() {MyClass obj(10, 20);obj.print(); // 输出: x: 10, y: 20return 0;
}

4.初始化 const 成员变量
const 成员变量必须在对象构造时完成初始化,且不能在构造函数体内赋值。

#include <iostream>
class MyClass {
private:const int value; // const 成员变量
public:MyClass(int v) : value(v) {} // 初始化列表初始化void print() {std::cout << "Value: " << value << std::endl;}
};int main() {MyClass obj(42);obj.print(); // 输出: Value: 42return 0;
}

5.初始化引用成员变量
引用类型的成员变量必须通过初始化列表进行初始化

#include <iostream>
class MyClass {
private:int& ref; // 引用类型成员
public:MyClass(int& r) : ref(r) {}void print() {std::cout << "Reference value: " << ref << std::endl;}
};int main() {int x = 100;MyClass obj(x);obj.print(); // 输出: Reference value: 100return 0;
}

6.初始化类类型成员变量
当类中包含其他类类型的成员时,这些成员的构造函数只能通过初始化列表调用。

#include <iostream>class Member {
private:int value;
public:Member(int v) : value(v) {std::cout << "Member constructed with value: " << value << std::endl;}
};class MyClass {
private:Member member; // 类类型成员
public:MyClass(int v) : member(v) {} // 初始化列表调用 Member 的构造函数
};int main() {MyClass obj(42);return 0;
}

输出:

Member constructed with value: 42

7.初始化基类和虚基类
派生类构造函数必须通过初始化列表调用基类的构造函数,尤其是基类没有默认构造函数时。

#include <iostream>class Base {
private:int value;
public:Base(int v) : value(v) {std::cout << "Base constructed with value: " << value << std::endl;}
};class Derived : public Base {
public:Derived(int v) : Base(v) { // 初始化列表调用基类构造函数std::cout << "Derived constructed" << std::endl;}
};int main() {Derived obj(42);return 0;
}

输出:

Base constructed with value: 42
Derived constructed

8.初始化列表的成员初始化顺序
成员变量的初始化顺序与它们在类中声明的顺序一致,而不是初始化列表的顺序。

#include <iostream>
class MyClass {
private:int a;int b;
public:MyClass(int x, int y) : b(y), a(x) { // 初始化顺序仍是 a -> bstd::cout << "a: " << a << ", b: " << b << std::endl;}
};int main() {MyClass obj(1, 2); // 输出: a: 1, b: 2return 0;
}

十、C++中的浅拷贝操作

浅拷贝(Shallow Copy)是C++中对象复制的一种方式,它复制对象中的非动态成员或指针成员的地址,而不是指针指向的实际内容。这种方式简单且高效,但可能带来潜在的问题,例如多个对象共享同一块内存区域时的资源冲突。

浅拷贝的特点:

  • 成员逐位复制: 浅拷贝直接将源对象的所有成员逐位复制到目标对象,包括指针的地址。
  • 效率高: 浅拷贝通常只需完成简单的内存操作,无需额外的深层处理。
  • 潜在问题: 由于共享了相同的动态内存,可能导致双重释放或数据不一致等问题。

浅拷贝一般由编译器自动生成的拷贝构造函数或赋值运算符完成,例如:

#include <iostream>
#include <cstring> // For std::strcpyclass ShallowCopyExample {
private:char* data;public:// 构造函数ShallowCopyExample(const char* initValue) {data = new char[strlen(initValue) + 1];std::strcpy(data, initValue);std::cout << "Constructor: Allocated memory for " << data << std::endl;}// 默认拷贝构造函数(浅拷贝)ShallowCopyExample(const ShallowCopyExample& other) = default;// 默认赋值运算符(浅拷贝)ShallowCopyExample& operator=(const ShallowCopyExample& other) = default;// 打印数据void print() const {std::cout << "Data: " << data << std::endl;}// 析构函数~ShallowCopyExample() {std::cout << "Destructor: Deleting memory for " << data << std::endl;delete[] data; // 如果多个对象共享同一块内存,这里会出错}
};int main() {ShallowCopyExample obj1("Hello");ShallowCopyExample obj2 = obj1; // 调用浅拷贝构造函数obj2.print();return 0; // 退出时,可能发生双重释放错误
}

输出示例:

Constructor: Allocated memory for Hello
Data: Hello
Destructor: Deleting memory for Hello
Destructor: Deleting memory for Hello // 可能导致崩溃

十一、C++中的深拷贝操作

深拷贝(Deep Copy)是C++中一种对象复制策略,其核心思想是复制对象中的数据内容,而不是直接共享指针或引用的内存地址。深拷贝的目的是确保每个对象都有自己独立的资源,避免资源冲突或双重释放等问题。

深拷贝的特点:

  • 独立性: 深拷贝为新对象分配新的内存并复制数据,因此新旧对象互不干扰。
  • 安全性: 深拷贝避免了浅拷贝中常见的资源管理问题,如双重释放或数据污染。
  • 代价: 深拷贝通常比浅拷贝消耗更多的资源和时间,因为它需要分配新的内存并复制数据。

深拷贝的实现:

#include <iostream>
#include <cstring> // For std::strcpyclass DeepCopyExample {
private:char* data; // 动态分配的资源public:// 构造函数DeepCopyExample(const char* initValue) {data = new char[strlen(initValue) + 1];std::strcpy(data, initValue);std::cout << "Constructor: Allocated memory for " << data << std::endl;}// 深拷贝构造函数DeepCopyExample(const DeepCopyExample& other) {data = new char[strlen(other.data) + 1];std::strcpy(data, other.data);std::cout << "Copy Constructor: Allocated new memory for " << data << std::endl;}// 深拷贝赋值运算符DeepCopyExample& operator=(const DeepCopyExample& other) {if (this != &other) { // 避免自我赋值delete[] data; // 释放已有内存data = new char[strlen(other.data) + 1];std::strcpy(data, other.data);std::cout << "Assignment Operator: Re-allocated memory for " << data << std::endl;}return *this;}// 打印数据void print() const {std::cout << "Data: " << data << std::endl;}// 析构函数~DeepCopyExample() {std::cout << "Destructor: Deleting memory for " << data << std::endl;delete[] data;}
};int main() {DeepCopyExample obj1("Hello");    // 构造对象DeepCopyExample obj2 = obj1;     // 调用拷贝构造函数obj2.print();DeepCopyExample obj3("World");obj3 = obj1;                     // 调用赋值运算符obj3.print();return 0;
}

输出结果:

Constructor: Allocated memory for Hello
Copy Constructor: Allocated new memory for Hello
Data: Hello
Constructor: Allocated memory for World
Assignment Operator: Re-allocated memory for Hello
Data: Hello
Destructor: Deleting memory for Hello
Destructor: Deleting memory for Hello
Destructor: Deleting memory for Hello

深拷贝与浅拷贝的比较
在这里插入图片描述

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

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

相关文章

vue CSS 自定义宽高 翻页 剥离 效果

新增需求&#xff0c;客户需要类似PPT的剥离效果用于WEB页面翻页&#xff0c;查找资料后&#xff0c;参考下方的掘金博主的文章&#xff0c;并将HTML修改成vue的页面进行使用。其中宽度、高度改成了变量&#xff0c;样式style中的属性与宽高的关系整理成了公式进行动态计算。 …

拿到小米 Offer,却迷茫了。。

大家好&#xff0c;我是程序员鱼皮&#xff0c;12 月了&#xff0c;很多小伙伴也拿到了秋招的 Offer&#xff08;没拿到也不要灰心&#xff09;&#xff0c;但即使拿到 Offer&#xff0c;可能还会有一些其他的顾虑。今天分享我们编程导航一位鱼友的提问&#xff0c;给大家作为学…

transformer学习笔记-自注意力机制(2)

经过上一篇transformer学习笔记-自注意力机制&#xff08;1&#xff09;原理学习&#xff0c;这一篇对其中的几个关键知识点代码演示&#xff1a; 1、整体qkv注意力计算 先来个最简单未经变换的QKV处理&#xff1a; import torch Q torch.tensor([[3.0, 3.0,0.0],[0.5, 4…

Leecode刷题C++之形成目标字符串需要的最少字符串数①

执行结果:通过 执行用时和内存消耗如下&#xff1a; 代码如下&#xff1a; class Solution { public:int minValidStrings(vector<string>& words, string target) {auto prefix_function [](const string& word, const string& target) -> vector<…

CompletableFuture异步业务 默认ForkJoinPool 导致类加载器加载类失败

目录 1、Bug案发现场 2、捉虫过程过程 3、解决方案与代码 4、成果展现与总结 ​编辑 5、参考文章 1、Bug案发现场 最近参与帮助以前同事实际业务开发中业务&#xff0c;在一个业务场景之中&#xff1b;使用H5页面通过二维码收集小微企业/个体工商户贷款业务需求。其中在获…

mybatis-plus超详细讲解

mybatis-plus &#xff08;简化代码神器&#xff09; 地址&#xff1a;https://mp.baomidou.com/ 目录 mybatis-plus 简介 特性 支持数据库 参与贡献 快速指南 1、创建数据库 mybatis_plus 2、导入相关的依赖 3、创建对应的文件夹 4、编写配置文件 5、编写代码 …

Houdini abc 导入 maya uv无法识别

参考&#xff1a;Houdini导出abc 至maya UV 无法识别_houdini导出abc没有uv-CSDN博客 从maya导入到houdini的uv默认是vertex层级的&#xff0c;而在maya中&#xff0c;uv是在point层级的&#xff1b;因此在houdini中导出abc时应将uv转为点层级&#xff0c;使用vertexsplit节点&…

2025erp系统开源免费进销存系统搭建教程/功能介绍/上线即可运营软件平台源码

系统介绍 基于ThinkPHP与LayUI构建的全方位进销存解决方案 本系统集成了采购、销售、零售、多仓库管理、财务管理等核心功能模块&#xff0c;旨在为企业提供一站式进销存管理体验。借助详尽的报表分析和灵活的设置选项&#xff0c;企业可实现精细化管理&#xff0c;提升运营效…

半导体数据分析(二):徒手玩转STDF格式文件 -- 码农切入半导体系列

一、概述 在上一篇文章中&#xff0c;我们一起学习了STDF格式的文件&#xff0c;知道了这是半导体测试数据的标准格式文件。也解释了为什么码农掌握了STDF文件之后&#xff0c;好比掌握了切入半导体行业的金钥匙。 从今天开始&#xff0c;我们一起来一步步地学习如何解构、熟…

OCR:文字识别

使用场景: 远程身份认证 自动识别录入用户身份/企业资质信息&#xff0c;应用于金融、政务、保险、电商、直播等场景&#xff0c;对用户、商家、主播进行实名身份认证&#xff0c;有效降低用户输入成本&#xff0c;控制业务风险 文档电子化 识别提取各类办公文档、合同文件、企…

深入C语言文件操作:从库函数到系统调用

引言 文件操作是编程中不可或缺的一部分&#xff0c;尤其在C语言中&#xff0c;文件操作不仅是处理数据的基本手段&#xff0c;也是连接程序与外部世界的重要桥梁。C语言提供了丰富的库函数来处理文件&#xff0c;如 fopen、fclose、fread、fwrite 等。然而&#xff0c;这些库…

linux上qt打包(二)

sudo apt install git 新建一个文件夹 名为xiazai&#xff0c; chmod -R 777 xiazai cd xiazai 并进入这个文件夹&#xff0c;然后clone git clone https://github.com/probonopd/linuxdeployqt.git 此处可能要fanQiang才能下 cd linuxdeployqt文件夹 下载平台需要的…

Windos中解决redis-server.exe闪退问题

一、闪退原因 &#xff08;一&#xff09;数据状态异常 数据不一致 在 Redis 运行过程中&#xff0c;如果发生意外情况&#xff0c;如突然断电、系统崩溃或者不正确的操作&#xff0c;可能会导致数据在内存中的存储状态不一致。例如&#xff0c;Redis 使用多种数据结构&#x…

【数据分享】2013-2023年我国省市县三级的逐年CO数据(免费获取\excel\shp格式)

空气质量数据是在我们日常研究中经常使用的数据&#xff01;之前我们给大家分享了2000-2023年的省市县三级的逐年PM2.5数据、2000-2023年的省市县三级的逐年PM10数据、2013-2023年的省市县三级的逐年SO2数据、2000-2023年省市县三级的逐年O3数据和2008-2023年我国省市县三级的逐…

华为WLAN基础配置(AC6005模拟配置)

AC6005基础配置 本次实验模拟华为AC6005的基本配置 Tip display interface GigabitEthernet 0/0/0 查看ap接口mac 前提条件&#xff1a;Vlan10为业务网段&#xff0c;vlan100为管理网段&#xff0c;5700作为dhcp。 5700配置如下 <Huawei>sy [Huawei]sys 5700 //设…

shell编程2 永久环境变量和字符串显位

声明 学习视频来自B站UP主 泷羽sec 常见变量 echo $HOME &#xff08;家目录 root用户&#xff09; /root cd /root windows的环境变量可以去设置里去新建 为什么输入ls dir的命令的时候就会输出相应的内容呢 因为这些命令都有相应的变量 which ls 通过这个命令查看ls命令脚本…

WebRTC服务质量(05)- 重传机制(02) NACK判断丢包

WebRTC服务质量&#xff08;01&#xff09;- Qos概述 WebRTC服务质量&#xff08;02&#xff09;- RTP协议 WebRTC服务质量&#xff08;03&#xff09;- RTCP协议 WebRTC服务质量&#xff08;04&#xff09;- 重传机制&#xff08;01) RTX NACK概述 WebRTC服务质量&#xff08;…

AI工具如何深刻改变我们的工作与生活

在当今这个科技日新月异的时代&#xff0c;人工智能&#xff08;AI&#xff09;已经从科幻小说中的概念变成了我们日常生活中不可或缺的一部分。从智能家居到自动驾驶汽车&#xff0c;从医疗诊断到金融服务&#xff0c;AI正以惊人的速度重塑着我们的世界。 一、工作方式的革新…

基于matlab的单目相机标定

链接&#xff1a; 单目相机标定&#xff08;使用Matlab&#xff09; 用Matlab对单目相机参数的标定步骤&#xff08;保姆级教程&#xff09; 1.准备代码 调用摄像头代码&#xff08;用于测试摄像头是否可用&#xff09;&#xff1a; #https://blog.csdn.net/qq_37759113/art…

[maven]使用spring

为了更好理解springboot&#xff0c;我们先通过学习spring了解其底层。 这里讲一下简单的maven使用spring框架入门使用。因为这一块的东西很多都需要联合起来后才好去细讲&#xff0c;本篇通过spring-context大致地介绍相关内容。 注意&#xff1a;spring只是一个框架&#xff…