一、函数定义

在 C++ 中,函数是组织代码逻辑的基本单元,用于实现模块化、复用、结构清晰的程序设计。


1、函数的基本结构

返回类型 函数名(参数列表) {
// 函数体
return 值; // 可选,视返回类型而定
}

声明(Declaration):

告诉编译器函数存在,通常放在头文件中:

int add(int a, int b);  // 函数声明

定义(Definition):

提供函数实现,通常放在 .cpp 文件中:

int add(int a, int b) {
return a + b;
}

2、函数重载(Overload)

同一个函数名可以定义多个参数不同的函数:

void print(int x);
void print(double x);
void print(std::string s);

注意:参数数量或类型不同才能构成重载,返回类型不同不能单独构成重载。


3、默认参数值

void greet(std::string name = "Guest") {
std::cout << "Hello, " << name << "!\n";
} greet(); // 输出 Hello, Guest!
greet("Alice"); // 输出 Hello, Alice!

4、内联函数(inline

建议编译器将函数代码插入调用处,适用于短小频繁调用的函数。

inline int square(int x) {
return x * x;
}

5、虚函数与纯虚函数

在 C++ 中,虚函数(virtual纯虚函数(= 0是实现 多态性 的关键机制,但它们在语法、用途、作用上有所不同。

特性 虚函数(Virtual Function) 纯虚函数(Pure Virtual Function)
定义方式 virtual void foo(); virtual void foo() = 0;
是否有实现 可以有实现(也可以没有) 必须在子类中实现(抽象接口)
是否必须重写 子类可选是否重写 子类必须重写(除非子类也是抽象类)
所在类 可以在任何类中 必须出现在抽象类中(即包含纯虚函数的类)
创建对象 可以实例化含虚函数的类 抽象类不可被实例化
用途 提供多态行为的默认实现 强制子类实现,作为接口规范

1. 虚函数示例(可重写)

class Animal {
public:
virtual void speak() {
std::cout << "Animal speaks\n";
}
}; class Dog : public Animal {
public:
void speak() override {
std::cout << "Dog barks\n";
}
}; Animal* p = new Dog();
p->speak(); // 输出:Dog barks(多态)

如果 Dog 不重写 speak(),则会使用 Animal 的默认实现。


2. 纯虚函数示例(强制重写)

class Shape {
public:
virtual void draw() = 0; // 纯虚函数
}; class Circle : public Shape {
public:
void draw() override {
std::cout << "Drawing Circle\n";
}
}; // Shape s; // 错误,抽象类不能实例化
Shape* p = new Circle();
p->draw(); // 输出:Drawing Circle

Circle 不实现 draw(),它也将变为抽象类。

接口类(interface)

C++ 没有 interface 关键字,但你可以用纯虚函数模拟接口类:

class IStream {
public:
virtual void read() = 0;
virtual void write() = 0;
virtual ~IStream() {} // 接口类应定义虚析构
};

6、Lambda 表达式(C++11 起)

[捕获列表](参数列表) -> 返回类型 {
函数体
}

其中:

  • []:捕获列表(可以捕获外部变量)
  • ():参数列表
  • ->:返回类型(可省略)
  • {}:函数体

匿名函数,通常用于简洁回调:

auto add = [](int a, int b) -> int {
return a + b;
};
std::cout << add(3, 5); // 输出:8 //返回类型如果能推导,可以省略 `-> int`:
auto add = [](int a, int b) {
return a + b;
};
std::cout << add(3, 4); // 输出 7

Lambda 表达式是 C++11 引入的一种匿名函数,用于定义可内联的函数对象,特别适合临时、小巧的函数使用场景,如算法回调、事件处理、线程创建等。

捕获外部变量(capture)

捕获方式 示例 说明
值捕获 [x] 捕获变量 x 的值(拷贝)
引用捕获 [&x] 捕获变量 x 的引用
捕获全部(值) [=] 捕获所有外部变量的值
捕获全部(引用) [&] 捕获所有外部变量的引用
混合捕获 [=, &y] y 外其他变量值捕获
int x = 10;
int y = 5; auto f = [=, &y]() {
// x 是值捕获,y 是引用捕获
std::cout << x + y << "\n";
y += 1; // 允许修改 y
}; f();

常见应用场景

  1. 与 STL 算法结合(如 std::sort
std::vector<int> v = {4, 2, 5, 1};
std::sort(v.begin(), v.end(), [](int a, int b) {
return a < b;
});
  1. 与线程一起使用:
#include <thread>
std::thread t([] {
std::cout << "In thread\n";
});
t.join();

可变 lambda(mutable

默认情况下,值捕获的变量是不可修改的。加上 mutable 可以让其变为可变:

int x = 5;
auto f = [x]() mutable {
x += 1; // 允许修改捕获变量的副本
std::cout << x;
};
f(); // 输出 6,但外部 x 不变

特殊函数类型

类型 用途
构造函数 创建对象时自动调用
析构函数 对象销毁时自动调用
拷贝构造函数 对象以另一个对象初始化时调用
移动构造函数 右值初始化对象时调用
运算符重载函数 重载 +, ==
虚函数 用于多态
纯虚函数 抽象类成员函数

二、函数参数值传递与引用传递

在 C++ 中,函数参数默认是值传递(pass-by-value),但 并不都是值传递,C++ 支持多种参数传递方式,主要包括以下几种:


1. 值传递(Pass by Value)

  • 将实参的副本传入函数
  • 函数内对参数的修改不会影响原变量
void foo(int x) {
x = 100;
} int main() {
int a = 10;
foo(a);
std::cout << a; // 输出 10,不变
}

2. 引用传递(Pass by Reference)

  • 传入变量的别名,函数内对其修改会影响原变量
void foo(int& x) {
x = 100;
} int main() {
int a = 10;
foo(a);
std::cout << a; // 输出 100,被修改了
}

3. 指针传递(Pass by Pointer)

  • 函数接收变量的地址,通过指针访问和修改
void foo(int* x) {
*x = 100;
} int main() {
int a = 10;
foo(&a);
std::cout << a; // 输出 100
}

4. 常引用传递(Pass by const Reference)

  • 适用于避免拷贝开销,但又不允许函数修改实参
  • 常用于传递大型对象,如 std::string, std::vector
void print(const std::string& s) {
std::cout << s;
}

5. 右值引用(Pass by rvalue reference)C++11+

  • 支持移动语义,避免不必要的深拷贝
void foo(std::string&& s) {
std::cout << s;
} foo("hello"s); // 移动传参

小结对照表:

方式 是否复制 是否可修改原变量 适用场景
值传递 小数据类型(int, float)
引用传递 需要修改原变量
指针传递 类似引用,但更灵活
const 引用传递 传大型对象且不修改
右值引用传递 支持移动,避免拷贝

结论:

C++ 中函数参数默认是值传递,但你可以通过 &(引用)、*(指针)或 &&(右值引用)来实现其他传参方式。

三、构造函数 析构函数

构造函数Constructor

构造函数是当对象被创建时自动调用的特殊函数,用于初始化对象的成员变量

  • 名字与类名相同
  • 没有返回值
  • 可以有多个
类型 用途
默认构造函数 不带参数或所有参数有默认值
带参构造函数 用户提供初始化参数
拷贝构造函数 用已有对象创建新对象(传值方式)
移动构造函数(C++11) 用于资源“窃取”(效率更高)
委托构造函数(C++11) 在一个构造函数中调用另一个构造函数

拷贝构造函数 Copy Constructor

如果你没有显式定义 operator=(),C++ 会默认生成一个浅拷贝的赋值运算符,对每个成员做成员赋值。但如果你类中包含裸指针等资源,默认赋值将产生浅拷贝问题(资源共享,析构冲突),此时应自定义赋值运算符。

拷贝构造作用:

  • 通过一个已有对象初始化另一个对象
  • 将对象按值传递给函数
  • 函数按值返回对象
ClassName(const ClassName& other);

参数是 const & 避免递归调用自身

禁止拷贝构造:

// 在 C++11/14/17 中,推荐使用 `= default` 和 `= delete` 明确指定:
class MyClass {
public:
MyClass() = default;
MyClass(const MyClass&) = delete;
~MyClass() = default;
};

析构函数 Destructor

析构函数是在对象销毁时自动调用的特殊函数,用于释放资源、关闭文件、清理指针等

  • 名字为 ~类名
  • 没有参数,没有返回值
  • 每个类最多只能有一个析构函数
  • 可以是虚的(用于多态删除)

示例

将定义和实现全部写在头文件中的写法:

#include <iostream>
#include <string> class Person {
public:
std::string name;
int* age; // 1. 默认构造函数(委托给带参构造)
Person() : Person("unknown", 0) {
std::cout << "Default constructor called (delegated)\n";
} // 2. 带参构造函数
Person(const std::string& name_, int age_) {
name = name_;
age = new int(age_);
std::cout << "Parameterized constructor called\n";
} // 3. 拷贝构造函数(深拷贝)
Person(const Person& other) {
name = other.name;
age = new int(*other.age);
std::cout << "Copy constructor called\n";
} // 4. 移动构造函数(C++11)
Person(Person&& other) noexcept {
name = std::move(other.name); // string 自带 move
age = other.age; // 窃取指针
other.age = nullptr; // 避免析构 double free
std::cout << "Move constructor called\n";
} // 5. 析构函数
~Person() {
std::cout << "Destructor called for " << name << "\n";
delete age;
}
};

现代c++推荐头文件和源文件分离,分离的写法:

// Person.h
#ifndef PERSON_H
#define PERSON_H #include <string> class Person {
public:
std::string name;
int* age;
// 1.默认构造函数
Person();
// 2.带参构造函数
Person(const std::string& name_, int age_);
// 3.拷贝构造函数(深拷贝)
Person(const Person& other);
// 4.移动构造函数(C++11)
Person(Person&& other) noexcept;
// 5.析构函数
virtual ~Person(); // 拷贝赋值运算符(可选)
Person& operator=(const Person& other);
// 移动赋值运算符(可选)
Person& operator=(Person&& other) noexcept; // const表示该函数不会修改类成员变量,如果在常函数里修改成员变量会报错
virtual void introduce() const;
}; #endif
// Person.cpp
#include "Person.h"
#include <iostream> // 1.默认构造函数
Person::Person() : Person("unknown", 0) {
std::cout << "Default constructor called\n";
} // 2.带参构造函数
Person::Person(const std::string& name_, int age_) {
name = name_;
age = new int(age_);
std::cout << "Parameterized constructor called\n";
} // 3.拷贝构造函数(深拷贝)
Person::Person(const Person& other) {
name = other.name;
age = new int(*other.age);
std::cout << "Copy constructor called\n";
} // 4.移动构造函数(C++11)
Person::Person(Person&& other) noexcept {
name = std::move(other.name);
age = other.age;
other.age = nullptr;
std::cout << "Move constructor called\n";
} // 5.析构函数
Person::~Person() {
std::cout << "Person destructor called for " << name << "\n";
delete age;
} // 拷贝赋值运算符(可选)
Person& Person::operator=(const Person& other) {
if (this != &other) {
name = other.name;
delete age;
age = new int(*other.age);
}
return *this;
} // 移动赋值运算符(可选)
Person& Person::operator=(Person&& other) noexcept {
if (this != &other) {
name = std::move(other.name);
delete age;
age = other.age;
other.age = nullptr;
}
return *this;
} void Person::introduce() const {
std::cout << "Hi, I am " << name << ", age " << *age << ".\n";
}

默认构造/拷贝/析构行为总结

函数类型 是否自动生成 什么时候需要自定义?
构造函数 (如果没写) 成员需要特殊初始化逻辑时
拷贝构造函数 (如果没写) 含指针资源、句柄或禁止拷贝
析构函数 (如果没写) 成员包含动态资源(如 new)时需释放
移动构造函数 (C++11+) 优化效率或防止拷贝
  • 如果你不写,编译器会自动生成一个“浅拷贝”版本。
  • 如果类中有裸指针,一定要自己写拷贝构造,否则可能引发双重释放错误。

深拷贝和浅拷贝

C++ 中的 深拷贝(deep copy)浅拷贝(shallow copy) 是对象复制时的两种方式,区别在于是否真正复制了堆上资源。理解这两者对掌握类的构造函数、拷贝构造函数和析构函数至关重要。

一、定义和区别

特性 浅拷贝(Shallow Copy) 深拷贝(Deep Copy)
拷贝内容 只复制指针的地址 分配新内存并复制数据内容
资源共享 原对象和副本指向同一内存 原对象和副本各自拥有独立内存
安全性 改变一个对象会影响另一个;易发生悬垂指针、双重释放 对象互不影响
析构风险 多次析构同一块内存(如果未正确管理) 每个对象析构各自拥有的内存

二、示例演示

#include <iostream>
#include <cstring> class Person {
public:
char* name; // 构造函数
Person(const char* n) {
name = new char[strlen(n) + 1];
strcpy(name, n);
} // 浅拷贝构造函数(默认)
// Person(const Person& other) = default; // 深拷贝构造函数
Person(const Person& other) {
name = new char[strlen(other.name) + 1];
strcpy(name, other.name);
} // 析构函数
~Person() {
delete[] name;
} void print() {
std::cout << "Name: " << name << std::endl;
}
};

如果不写深拷贝构造函数,编译器默认使用浅拷贝,即只是复制了指针 name 的地址,两个对象共用同一块堆内存。这样一来,修改 p2.name 会影响 p1.name,两个对象析构时还会重复释放同一块内存,导致崩溃。


三、默认拷贝行为说明

操作类型 默认行为 是否安全
拷贝构造函数 浅拷贝
赋值运算符 = 浅赋值
析构函数 默认释放 (若使用裸指针)

const在类中的作用

const 可以修饰类的成员函数函数参数与返回值和对象,但它不能直接修饰整个类本身


const 修饰函数(常成员函数)

class MyClass {
public:
int getValue() const; // 表示该函数不会修改类成员变量
private:
int value = 42;
};
int MyClass::getValue() const {
// this->value = 10; 编译错误:不能修改成员变量
return value;
}
const MyClass obj;   //  **只能调用 const 成员函数**
MyClass obj2; // **既可以调用 const 成员函数,也可以调用非常成员函数**

const 修饰函数参数和返回值

修饰参数

void printName(const std::string& name); //  避免拷贝 + 保证不修改参数

修饰返回值

const std::string& getName() const; //  返回值不能被修改(防止误用)

注意:const 修饰返回值时,通常用于返回引用或指针,不太常用于值返回。


不能直接修饰类

const class MyClass {}; //  不常见,基本无意义

四、继承

基类函数用 virtual 修饰,子类可以 override

继承方式 修饰符可见性

c++ Java中的继承方式是完全一样的,继承方式

继承方式 基类的 public 成员在子类中变成 基类的 protected 成员在子类中变成 基类的 private 成员
public 继承 public protected 不可访问
protected 继承 protected protected 不可访问
private 继承 private private 不可访问

可见性

修饰符 类内访问 派生类访问 类外访问
public 可访问 可访问 可访问
protected 可访问 可访问 不可访问
private 可访问 不可访问 不可访问

示例

//student.h
#ifndef STUDENT_H
#define STUDENT_H #include "Person.h" class Student : public Person {
public:
std::string school; Student();
Student(const std::string& name_, int age_, const std::string& school_);
~Student() override; void introduce() const override;
}; #endif
//student.cpp
#include "Student.h"
#include <iostream> Student::Student() : Person("unknown_student", 18), school("Unknown School") {
std::cout << "Student default constructor\n";
} Student::Student(const std::string& name_, int age_, const std::string& school_)
: Person(name_, age_), school(school_) {
std::cout << "Student parameterized constructor\n";
} Student::~Student() {
std::cout << "Student destructor called for " << name << "\n";
} void Student::introduce() const {
std::cout << "Hi, I am student " << name << ", age " << *age
<< ", studying at " << school << ".\n";
}

构造函数和析构函数的顺序

  • 构造顺序:先构造基类 → 再构造派生类
  • 析构顺序:先析构派生类 → 再析构基类
class Base {
public:
Base() { std::cout << "Base()\n"; }
~Base() { std::cout << "~Base()\n"; }
}; class Derived : public Base {
public:
Derived() { std::cout << "Derived()\n"; }
~Derived() { std::cout << "~Derived()\n"; }
};

输出顺序:

Base()
Derived()
~Derived()
~Base()

C++特有:多继承与虚继承 菱形继承问题

多继承

class A { public: int x; };
class B { public: int x; };
class C : public A, public B {}; // 多继承,C 有两个 x,需区分 A::x 和 B::x

菱形继承问题(Diamond Problem)”是 C++ 多继承中特有的一种继承结构冲突问题,会导致:

  1. 基类子对象重复
  2. 数据二义性 / 歧义访问
  3. 构造和析构混乱
  4. 资源浪费

一、什么是菱形继承结构?

如下图所示,BC 都继承自 A,而 D 同时继承自 BC

      A
/ \
B C
\ /
D
class A {
public:
int value;
}; class B : public A {};
class C : public A {};
class D : public B, public C {};

二、菱形继承引发的问题

1. 产生 多个 A 子对象

D 中包含了 两个 A 对象

  • 一个来自 B(B→A)
  • 一个来自 C(C→A)

2. 访问 value 发生歧义

D d;
d.value = 10; // 错误:编译器不知道是 B::A::value 还是 C::A::value

必须手动指定:

d.B::value = 10;
d.C::value = 20;

三、解决方法:虚继承(virtual

virtual 修饰继承关系,让 B 和 C 共享同一个 A 子对象

class A {
public:
int value;
}; class B : virtual public A {};
class C : virtual public A {};
class D : public B, public C {};

虚继承效果:

  • D 中只有 一个 A 对象,由编译器自动协调
  • 访问成员不再歧义:
D d;
d.value = 10; // 正常访问,无歧义

五、友元

在 C++ 中,友元(friend)机制允许非成员函数或其他类访问某个类的私有(private)和受保护(protected)成员。友元关系是 单向不传递 的,常用于操作符重载、调试工具或两个类之间的紧密协作等场景。


一、友元的三种形式

1. 友元函数(Friend Function)

class Box {
private:
int width;
public:
Box(int w) : width(w) {} // 声明友元函数
friend void printWidth(const Box& b);
}; // 非成员函数,可以访问 Box 的私有成员
void printWidth(const Box& b) {
std::cout << "Width: " << b.width << std::endl;
}

特点

  • 非类成员函数,但拥有类的访问权限
  • 常用于重载 operator<< 等操作符

2. 友元类(Friend Class)

class Engine;

class Car {
private:
int speed;
public:
Car(int s) : speed(s) {}
friend class Engine; // Engine 可以访问 Car 的私有成员
}; class Engine {
public:
void showSpeed(const Car& c) {
std::cout << "Speed: " << c.speed << std::endl;
}
};

特点

  • 一个类可以将另一个类声明为友元
  • 该友元类的所有成员函数都能访问被友元类的私有成员
  • 单向:Engine 是 Car 的朋友,但 Car 不可访问 Engine 的私有成员

3. 成员函数作为友元

class B;

class A {
private:
int a_val;
public:
A(int v) : a_val(v) {}
friend void B::printA(const A& a); // 只让 B 的某个成员函数成为友元
}; class B {
public:
void printA(const A& a) {
std::cout << a.a_val << std::endl;
}
};

注意:这种方式必须 先声明 B 类,否则编译器不知道 B::printA 是什么。


二、友元的特性总结

特性 说明
单向访问 被声明为友元的类/函数可以访问声明类的私有成员,反之不行
非成员也可声明为友元 普通函数、类、类的成员函数都可以作为友元
不破坏封装性 尽管能访问私有成员,但访问范围被显式限定
编译时绑定 友元关系在编译时建立,无法在运行时动态设置
不继承、不传递 子类不会继承友元权限,友元类的友元也无访问权

三、示例:重载 << 运算符

class Person {
private:
std::string name;
int age;
public:
Person(std::string n, int a) : name(n), age(a) {}
friend std::ostream& operator<<(std::ostream& os, const Person& p);
}; std::ostream& operator<<(std::ostream& os, const Person& p) {
os << "Name: " << p.name << ", Age: " << p.age;
return os;
}

c++ 函数 类的更多相关文章

  1. hdwiki model目录下的函数类

    model目录下的函数类    actions.class.php(站内地图相关) getHTML:获得页面菜单和相关信息 getMap:生成站内地图 adv.class.php 对wiki_adve ...

  2. MyEclipse上有main函数类运行报错:Editor does not contain a main type

    MyEclipse下有main函数类运行报错:Editor does not contain a main type 出现这种问题的原因是,该java文件所在的包没有被MyEclipse认定为源码包. ...

  3. bitMap算法实现以及ckHash函数类,将字符串映射成数字,同时可以将数字映射成字符串

    ckHash函数类,将字符串映射成数字,同时可以将数字映射成字符串 说明 1.所谓的BitMap就是用一个bit位来标记某个元素所对应的value,而key即是该元素,由于BitMap使用了bit位来 ...

  4. SQL函数类的操作,增加,查询

    数据库连接: 表的创建: 创建连接对象,命令对象类: 添加函数: 查询函数类: List<>集合,里面专门放对象 函数主体: 查询: foreach只能修改,不能添加删除

  5. 爬虫写法进阶:普通函数--->函数类--->Scrapy框架

    本文转载自以下网站: 从 Class 类到 Scrapy https://www.makcyun.top/web_scraping_withpython12.html 普通函数爬虫: https:// ...

  6. MyEclipse上有main函数类运行报错:Editor does not contain a

    MyEclipse下有main函数类运行报错:Editor does not contain a main type?出现这种问题的原因是,该java文件   MyEclipse下有main函数类运行 ...

  7. React函数类组件及其Hooks学习

    目录 函数类组件 函数式组件和类式组件的区别: 为什么要使用函数式组件? Hooks概念及常用的Hooks 1. useState: State的Hook 语法 useState()说明: setXx ...

  8. 常用PHP函数类目录

    说明:用来记录我在开发过程中,经常用到的一些常用函数或者常用类. 常用函数 PHP常用函数 (1) 常用类 PHP表单数据校验类

  9. 泛函编程(4)-深入Scala函数类

    既然是泛函编程,多了解一下函数自然是免不了的了: 方法(Method)不等于函数(Function) 方法不是函数但可以转化成函数:可以手工转换或者由编译器(compiler)在适当的情况下自动转换. ...

  10. PHP输出当前进程所有变量 / 常量 / 模块 / 函数 / 类

    <?php /* 不知道怎么打印某个函数的参数和相关分类类型的所有函数 以下函数如果没有参数,返回的都是一个数组get_defined_functions() 获取所有已经定义的函数get_de ...

随机推荐

  1. 实现领域驱动设计 - 使用ABP框架 - 系列文章汇总

    系列文章汇总 前言: 最近看到ABP官网的一本电子书,感觉写的很好,翻译出来,一起学习下 Implementing Domain Driven Design 实现领域驱动设计 - 使用ABP框架 - ...

  2. windows 本地部署DeepSeek

    一:前言: 那么为什么要本地部署,主要就是企业或者个人为了数据安全和防止受限网络等其 数据安全:数据不用上传到外面,在本地处理,不用担心数据泄露,像金融.医疗这些对数据安全要求高的行业特别需要. 功能 ...

  3. 面试题-JVM性能调优

    前言 JVM性能调优是一个很大的话题,很多中小企业的业务规模受限,没有迫切的性能调优需求,但是如果不知道JVM相关的理论知识,写出来的代码或者配置的JVM参数不合理时,就会出现很严重的性能问题,到时候 ...

  4. 深入掌握FastAPI与OpenAPI规范的高级适配技巧

    title: 深入掌握FastAPI与OpenAPI规范的高级适配技巧 date: 2025/03/30 01:16:11 updated: 2025/03/30 01:16:11 author: c ...

  5. IP地址查询服务

    IP地址查询站点 https://ip.cn/ http://ip.qq.com/ http://ip138.com/ https://www.apnic.net/ ... IP计算 ip地址在线计算 ...

  6. zk源码—1.数据节点与Watcher机制及权限

    大纲 1.ZooKeeper的数据模型.节点类型与应用 (1)数据模型之树形结构 (2)节点类型与特性(持久 + 临时 + 顺序 ) (3)节点的状态结构(各种zxid + 各种version) (4 ...

  7. 面试官:如果某个业务量突然提升100倍QPS你会怎么做?

    "假设你负责的系统,某个业务线的QPS突然暴增100倍,你会怎么应对?" --这是上周朋友去面试,被问到一道题,他答了"加机器扩容",结果面试官眉头一皱:&qu ...

  8. Java程序员的Go入门笔记

    系列文章目录和关于我 0.背景 3年java开发背景(因此这篇文章的特点是:比较适合java程序员doge),业余时间有了解过一些go,如今主要技术栈是go,此篇主要结合go语言圣经和团队内go项目, ...

  9. 机器人操作系统ROS2之简介

    什么是ROS2? ROS(机器人操作系统)是用于机器人应用的开源软件开发工具包.ROS 为各行业的开发者提供了一个标准的软件平台,帮助他们从研究和原型设计一直推进到部署和生产,从驱动程序到最先进的算法 ...

  10. MySQL 的查询优化器如何选择执行计划?

    MySQL 的查询优化器负责决定如何执行 SQL 查询,它会根据多个因素选择最优的执行计划.查询优化器的目标是选择一个成本最低.性能最优的执行计划,以便高效地处理查询.执行计划的选择是基于 MySQL ...