【C++学习笔记】【基础】2.类与对象(中)

🍕阿i索 个人主页
《C语言专栏》 《C++专栏》
《数据结构专栏》 《LaTeX专栏》
待更新...

本章节核心讲解类的 6 个默认成员函数,重点掌握构造、析构、拷贝构造、赋值运算符重载四大核心函数的特性、编译器默认行为及手动实现方式,同时理解运算符重载、const 成员函数等关键语法,是 C++ 面向对象封装特性的核心延伸。


一、类的默认成员函数

默认成员函数:用户未显式实现,编译器会自动生成的成员函数。一个空类编译器默认生成 6 个,C++11 后新增移动构造、移动赋值,核心重点为前 4 个:

默认成员函数 核心功能 关键说明
构造函数 完成对象的初始化 替代手动写的 Init 函数,自动调用
析构函数 完成对象的资源清理 替代手动写的 Destroy 函数,自动调用
拷贝构造函数 用同类对象初始化新对象 自定义类型拷贝行为必调用
赋值运算符重载 两个已存在对象间的拷贝赋值 区分拷贝构造,完成赋值行为
普通取地址运算符重载 返回普通对象的地址 编译器默认生成即可,极少手动实现
const 取地址运算符重载 返回 const 对象的地址 编译器默认生成即可,极少手动实现

学习核心🙂

  1. 未手动实现时,编译器默认生成的函数行为是什么,是否满足需求;
  2. 若默认行为不满足,如何手动实现(重点为深拷贝场景)。

二、构造函数

构造函数的核心任务不是开空间创建对象 (对象空间在实例化时已分配),而是在对象实例化时自动完成初始化,替代 C 语言中手动调用的 Init 函数。

2.1 构造函数的特性

基础规则 :函数名与类名一致,无返回值(无需写void);对象实例化时自动调用,且仅调用一次,支持函数重载。

编译器生成逻辑:未显式定义时,编译器自动生成无参默认构造;一旦手动定义任意构造,编译器不再生成。

默认构造与初始化:无需传参即可调用的默认构造包含无参、全缺省、编译器生成的无参构造(三者不可共存,否则调用歧义);编译器默认构造对内置类型成员初始化行为不确定,对自定义类型成员会自动调用其默认构造(无则编译报错)

类型区分

  • 内置类型:语言原生类型,如 int/char/double/ 指针等;
  • 自定义类型:用 class/struct 定义的类型,如 Stack/Date/MyQueue 等。

2.2 构造函数的实现示例

复制代码
#include<iostream>
using namespace std;

class Date
{
public:
    // 1. 无参构造函数
    Date()
    {
        _year = 1;
        _month = 1;
        _day = 1;
    }
    // 2. 带参构造函数(重载)
    Date(int year, int month, int day)
    {
        _year = year;
        _month = month;
        _day = day;
    }
    // 3. 全缺省构造函数(默认构造,二选一)
    /*Date(int year = 1, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }*/
    void Print()
    {
        cout << _year << "/" << _month << "/" << _day << endl;
    }
private:
    int _year;
    int _month;
    int _day;
};

int main()
{
    Date d1; // 调用无参/默认构造,不能加括号(Date d1()会被识别为函数声明)
    Date d2(2025, 7, 31); // 调用带参构造
    d1.Print();
    d2.Print();
    return 0;
}

2.3 自定义类型的构造调用

编译器默认生成的构造函数对自定义类型成员的初始化,会自动调用其默认构造:

复制代码
class Stack
{
public:
    // Stack的默认构造(全缺省)
    Stack(int n = 4)
    {
        _a = (int*)malloc(sizeof(int) * n);
        _capacity = n;
        _top = 0;
    }
private:
    int* _a;
    size_t _capacity;
    size_t _top;
};

// 自定义类型MyQueue,无显式构造
class MyQueue
{
private:
    Stack _pushst; // 自定义类型,自动调用Stack的默认构造
    Stack _popst;  // 自定义类型,自动调用Stack的默认构造
};

int main()
{
    MyQueue q; // 编译器生成MyQueue的默认构造,完成两个Stack成员的初始化
    return 0;
}

2.4 注意

  1. 无参构造创建对象时,对象后不能加括号Date d1()会被编译器识别为函数声明);
  2. 全缺省构造和无参构造不能同时存在,否则调用时产生歧义;
  3. 绝大多数场景需要手动实现构造函数,保证内置类型成员的确定性初始化。

三、析构函数

析构函数的核心任务不是销毁对象本身 (对象空间在生命周期结束时自动释放),而是在对象销毁时自动完成资源清理,替代 C 语言中手动调用的 Destroy 函数。

3.1 析构函数的特性

基础规则 :函数名是类名前加~,无参数、无返回值(无需写void);一个类仅能有一个析构函数,不支持重载;对象生命周期结束时自动调用,且仅调用一次。

编译器生成与成员处理:未显式定义时,编译器自动生成默认析构;默认析构对内置类型成员不处理,对自定义类型成员自动调用其析构(自定义类型成员无论是否手动实现类的析构,都会触发自身析构)。

调用与实现规则:局部域多个对象遵循 "后定义先析构"(栈后进先出);无堆资源的类(如 Date)可用默认析构,有资源申请的类(如 Stack)必须手动实现析构,否则导致内存泄漏

3.2 析构函数的实现示例

复制代码
#include<iostream>
#include<cstdlib>
using namespace std;

typedef int STDataType;
class Stack
{
public:
    // 构造:申请资源
    Stack(int n = 4)
    {
        _a = (STDataType*)malloc(sizeof(STDataType) * n);
        _capacity = n;
        _top = 0;
    }
    // 手动实现析构:释放资源
    ~Stack()
    {
        cout << "~Stack()" << endl;
        free(_a); // 释放堆空间
        _a = nullptr; // 置空避免野指针
        _top = _capacity = 0; // 重置成员
    }
private:
    STDataType* _a; // 指向堆资源,必须手动释放
    size_t _capacity;
    size_t _top;
};

// 无显式析构,编译器生成默认析构
class MyQueue
{
private:
    Stack _pushst; // 自定义类型,自动调用Stack的析构
    Stack _popst;  // 自定义类型,自动调用Stack的析构
};

int main()
{
    Stack st; // 生命周期结束时调用~Stack()
    MyQueue mq; // 生命周期结束时,编译器生成的~MyQueue()调用两个Stack的析构
    return 0;
}

3.3 析构函数对比 C 语言

C++ 的构造 + 析构自动调用,避免了 C 语言中忘记调用 Init/Destroy 的问题:

复制代码
// C++版Stack实现括号匹配(自动初始化、自动清理)
bool isValid(const char* s) {
    Stack st; // 实例化时调用构造,自动初始化
    while (*s)
    {
        if (*s == '[' || *s == '(' || *s == '{')
            st.Push(*s);
        else
        {
            if (st.Empty()) return false;
            char top = st.Top();
            st.Pop();
            if ((*s == ']' && top != '[') || (*s == '}' && top != '{') || (*s == ')' && top != '('))
                return false;
        }
        s++;
    }
    return st.Empty();
    // 函数结束,st生命周期结束,自动调用析构释放资源
}

// C语言版Stack实现括号匹配(手动初始化、手动清理,易遗漏)
bool isValid(const char* s) {
    ST st;
    STInit(&st); // 手动调用初始化
    while (*s)
    {
        // 业务逻辑与C++一致
    }
    bool ret = STEmpty(&st);
    STDestroy(&st); // 手动调用清理,忘记则内存泄漏
    return ret;
}

四、拷贝构造函数

拷贝构造函数是特殊的构造函数 ,用于用同类已存在的对象,初始化另一个即将创建的对象 ,C++ 规定自定义类型的拷贝行为必须调用拷贝构造

4.1 拷贝构造函数的特性

基础规则 :作为构造函数的重载,函数名与类名一致;首个参数必须是const 类名&(传值会引发无穷递归),其余参数若有则需带缺省值;未显式定义时,编译器自动生成默认版本。

默认拷贝逻辑:编译器生成的拷贝构造对内置类型做浅拷贝(按字节拷贝),对自定义类型自动调用其拷贝构造;但类含堆资源指针时,浅拷贝会导致多对象共享堆空间,引发数据混乱、重复释放资源等问题,需手动实现深拷贝(重新申请堆空间并拷贝数据)。

调用与注意事项:自定义类型传值传参 / 返回时会触发拷贝构造(引用方式则不会);局部对象的引用返回会产生野引用,需避免

4.2 拷贝构造的无穷递归原因

若拷贝构造的第一个参数为传值(Date d),则调用拷贝构造时,需要先将实参拷贝给形参,而拷贝实参又需要调用拷贝构造,形成无限递归:

复制代码
// 错误写法:传值参数,编译器直接报错
Date(Date d) 
{
    _year = d._year;
    _month = d._month;
    _day = d._day;
}
// 正确写法:const引用参数,避免拷贝
Date(const Date& d)
{
    _year = d._year;
    _month = d._month;
    _day = d._day;
}

4.3 拷贝构造的实现示例

4.3.1 浅拷贝(适用于无堆资源的类,如 Date)

复制代码
#include<iostream>
using namespace std;

class Date
{
public:
    Date(int year = 1, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }
    // 浅拷贝:编译器默认生成即可,手动实现仅作演示
    Date(const Date& d)
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }
    void Print() { cout << _year << "/" << _month << "/" << _day << endl; }
private:
    int _year;
    int _month;
    int _day; // 无堆资源,浅拷贝足够
};

int main()
{
    Date d1(2025, 8, 1);
    Date d2(d1); // 调用拷贝构造,用d1初始化d2
    Date d3 = d1; // 等价于d3(d1),**拷贝构造**(非赋值重载)
    d2.Print();
    d3.Print();
    return 0;
}

4.3.2 深拷贝(适用于有堆资源的类,如 Stack)

复制代码
#include<iostream>
#include<cstdlib>
#include<cstring>
using namespace std;

typedef int STDataType;
class Stack
{
public:
    Stack(int n = 4)
    {
        _a = (STDataType*)malloc(sizeof(STDataType) * n);
        _capacity = n;
        _top = 0;
    }
    // 手动实现深拷贝:为新对象重新申请资源
    Stack(const Stack& s)
    {
        // 1. 申请与原对象相同大小的堆空间
        _a = (STDataType*)malloc(sizeof(STDataType) * s._capacity);
        if (_a == nullptr)
        {
            perror("malloc fail");
            return;
        }
        // 2. 拷贝原对象的资源数据
        memcpy(_a, s._a, sizeof(STDataType) * s._top);
        // 3. 拷贝普通成员
        _capacity = s._capacity;
        _top = s._top;
    }
    // 析构:释放资源
    ~Stack()
    {
        free(_a);
        _a = nullptr;
        _capacity = _top = 0;
    }
    void Push(STDataType x) { /* 入栈逻辑 */ }
private:
    STDataType* _a; // 堆资源指针,必须深拷贝
    size_t _capacity;
    size_t _top;
};

int main()
{
    Stack st1;
    st1.Push(1);
    st1.Push(2);
    Stack st2(st1); // 深拷贝,st1和st2的_a指向不同堆空间
    return 0;
}

4.4 拷贝构造的调用场景

  1. 用已存在对象初始化新对象:Date d2(d1);Date d3 = d1;
  2. 自定义类型传值传参void Func(Date d)(d 为形参,由实参拷贝构造);
  3. 自定义类型传值返回Date Func()(返回值为临时对象,由函数内局部对象拷贝构造);
  4. 容器存储自定义类型:vector<Date> v; v.push_back(d1);(底层调用拷贝构造)。

4.5 引用传参 / 返回的注意

  • 引用传参void Func(const Date& d),不会调用拷贝构造,减少开销,推荐使用;

  • 引用返回 :若返回的是函数内的局部对象 ,函数结束后局部对象销毁,引用变为野引用 ,必须用传值返回

    // 错误:返回局部对象的引用,野引用
    Stack& Func3()
    {
    Stack st; // 局部对象,函数结束销毁
    return st;
    }
    // 正确:传值返回,调用拷贝构造生成临时对象
    Stack Func4()
    {
    Stack st;
    return st;
    }

五、运算符重载

C++ 允许为自定义类型重载运算符 ,赋予运算符新的含义,使自定义类型能像内置类型一样使用运算符,运算符重载是具有特殊名字的函数

5.1 运算符重载的基本语法

核心格式 :函数名固定为operator+要重载的运算符(如operator==operator+),具备返回值、参数列表和函数体;参数个数与运算对象数一致(一元运算符 1 个,二元运算符 2 个),若为类成员函数则首个运算对象由 this 指针隐式传递,参数个数比运算对象少 1。

重载规则 :优先级和结合性与内置类型一致,不可修改;必须包含至少一个类 / 枚举类型参数,无法重载内置类型运算符,也不能创建新运算符(如operator@);以下5个运算符禁止重载:.*、::、sizeof、?:、.

使用原则 :仅为有实际业务意义的运算符重载(如 Date 类重载-合理,重载+无意义)。

5.2 运算符重载的实现方式

5.2.1 全局函数重载

需解决类私有成员的访问问题,解决方案:①成员设为 public;②提供 getter 函数;③声明为友元函数;④改为成员函数重载(推荐)。

复制代码
#include<iostream>
using namespace std;

class Date
{
public:
    Date(int year, int month, int day) : _year(year), _month(month), _day(day) {}
    int _year;
    int _month;
    int _day; // 设为public,方便全局函数访问
};

// 全局函数重载==:二元运算符,两个参数
bool operator==(const Date& d1, const Date& d2)
{
    return d1._year == d2._year
        && d1._month == d2._month
        && d1._day == d2._day;
}

int main()
{
    Date d1(2025,8,1);
    Date d2(2025,8,2);
    cout << (d1 == d2) << endl; // 编译器转换为operator==(d1, d2)
    return 0;
}

5.2.2 类的成员函数重载

推荐方式,利用 this 指针隐式传递第一个运算对象,参数个数少 1,且可直接访问类的私有成员。

复制代码
#include<iostream>
using namespace std;

class Date
{
public:
    Date(int year, int month, int day) : _year(year), _month(month), _day(day) {}
    // 成员函数重载==:this指针指向d1,参数为d2
    bool operator==(const Date& d)
    {
        return _year == d._year
            && _month == d._month
            && _day == d._day;
    }
private:
    int _year;
    int _month;
    int _day;
};

int main()
{
    Date d1(2025,8,1);
    Date d2(2025,8,2);
    cout << (d1 == d2) << endl; // 编译器转换为d1.operator==(d2)
    cout << d1.operator==(d2) << endl; // 显式调用,与上等价
    return 0;
}

5.3 前置 / 后置 ++ 的重载区分

++ 有前置(++d)和后置(d++),函数名均为operator++,C++ 规定后置 ++ 重载时增加一个 int 形参(仅作区分,无需使用),与前置 ++ 构成重载。

复制代码
class Date
{
public:
    // 前置++:成员函数,返回引用(支持连续++)
    Date& operator++()
    {
        _day++;
        // 处理日期进位逻辑...
        return *this;
    }
    // 后置++:增加int形参,返回值(不支持连续++)
    Date operator++(int)
    {
        Date tmp = *this; // 先保存原对象
        _day++;
        // 处理日期进位逻辑...
        return tmp; // 返回原对象值
    }
private:
    int _year, _month, _day;
};

int main()
{
    Date d(2025,8,1);
    ++d; // 调用d.operator++()
    d++; // 调用d.operator++(0)(int形参传任意值均可)
    return 0;
}

5.4 流插入 / 流提取的重载

<<(流插入)、>>(流提取)需重载为全局函数 ,若重载为成员函数,this 指针会抢占第一个参数,导致调用形式变为d << cout(不符合使用习惯)。

复制代码
#include<iostream>
using namespace std;

class Date
{
    // 声明为友元,允许全局函数访问私有成员
    friend ostream& operator<<(ostream& out, const Date& d);
    friend istream& operator>>(istream& in, Date& d);
public:
    Date(int year = 1, int month = 1, int day = 1)
        : _year(year), _month(month), _day(day) {}
private:
    int _year, _month, _day;
};

// 流插入重载:cout << d
ostream& operator<<(ostream& out, const Date& d)
{
    out << d._year << "年" << d._month << "月" << d._day << "日";
    return out; // 返回out,支持连续输出:cout << d1 << d2
}

// 流提取重载:cin >> d
istream& operator>>(istream& in, Date& d)
{
    in >> d._year >> d._month >> d._day;
    return in; // 返回in,支持连续输入:cin >> d1 >> d2
}

int main()
{
    Date d1;
    cin >> d1;
    cout << d1 << endl;
    return 0;
}

六、赋值运算符重载

赋值运算符重载是特殊的运算符重载 ,属于默认成员函数,用于两个已存在的对象之间的拷贝赋值必须重载为类的成员函数

6.1 区分拷贝构造与赋值重载

场景 调用函数 核心差异
Date d2(d1); 拷贝构造 用 d1初始化新对象 d2(d2 未存在)
Date d2; d2 = d1; 赋值运算符重载 用 d1赋值给已存在的 d2(d2 已存在)

6.2 赋值运算符重载的特性

基础规则:必须重载为类的成员函数(禁止全局重载);未显式定义时,编译器自动生成默认版本,其对内置类型做浅拷贝、对自定义类型自动调用对应赋值重载。

参数与返回值 :参数建议为const 类名&(减少拷贝开销且保护原对象);返回值建议为类类型引用(返回*this),支持连续赋值。

深拷贝要求:函数体需判断自赋值(避免深拷贝场景的资源泄漏);含堆资源的类(如 Stack)必须手动实现深拷贝版重载,否则会出现浅拷贝导致的资源问题。

6.3 赋值运算符重载的实现示例

6.3.1 浅拷贝(适用于无堆资源的类,如 Date)

复制代码
#include<iostream>
using namespace std;

class Date
{
public:
    Date(int year = 1, int month = 1, int day = 1)
        : _year(year), _month(month), _day(day) {}
    Date(const Date& d) // 拷贝构造
        : _year(d._year), _month(d._month), _day(d._day) {}
    // 赋值运算符重载:浅拷贝
    Date& operator=(const Date& d)
    {
        // 自赋值判断
        if (this != &d)
        {
            _year = d._year;
            _month = d._month;
            _day = d._day;
        }
        return *this; // 返回自身,支持连续赋值
    }
    void Print() { cout << _year << "/" << _month << "/" << _day << endl; }
private:
    int _year, _month, _day;
};

int main()
{
    Date d1(2025,8,1);
    Date d2(2025,8,2);
    d2 = d1; // 调用赋值重载,d2已存在
    d2.Print();
    Date d3;
    d3 = d2 = d1; // 连续赋值,支持
    d3.Print();
    return 0;
}

6.3.2 深拷贝(适用于有堆资源的类,如 Stack)

复制代码
#include<iostream>
#include<cstdlib>
#include<cstring>
using namespace std;

typedef int STDataType;
class Stack
{
public:
    Stack(int n = 4)
    {
        _a = (STDataType*)malloc(sizeof(STDataType) * n);
        _capacity = n;
        _top = 0;
    }
    Stack(const Stack& s) // 拷贝构造(深拷贝)
    {
        _a = (STDataType*)malloc(sizeof(STDataType) * s._capacity);
        memcpy(_a, s._a, sizeof(STDataType) * s._top);
        _capacity = s._capacity;
        _top = s._top;
    }
    // 赋值运算符重载(深拷贝)
    Stack& operator=(const Stack& s)
    {
        if (this != &s) // 自赋值判断
        {
            // 1. 释放当前对象的原有资源
            free(_a);
            // 2. 重新申请资源,拷贝数据
            _a = (STDataType*)malloc(sizeof(STDataType) * s._capacity);
            if (_a == nullptr)
            {
                perror("malloc fail");
                return *this;
            }
            memcpy(_a, s._a, sizeof(STDataType) * s._top);
            // 3. 拷贝普通成员
            _capacity = s._capacity;
            _top = s._top;
        }
        return *this;
    }
    ~Stack()
    {
        free(_a);
        _a = nullptr;
        _capacity = _top = 0;
    }
private:
    STDataType* _a;
    size_t _capacity;
    size_t _top;
};

int main()
{
    Stack st1, st2;
    st1.Push(1);
    st1.Push(2);
    st2 = st1; // 深拷贝,st1和st2的_a指向不同堆空间
    return 0;
}

七、const 成员函数

7.1 概念与语法

const 成员函数 :用const修饰的类成员函数,const写在函数参数列表的后面,是 C++ 中保证对象只读性的重要语法。

复制代码
// 语法格式
class Date
{
public:
    void Print() const // const成员函数
    {
        cout << _year << "/" << _month << "/" << _day << endl;
    }
private:
    int _year, _month, _day;
};

7.2 特性

本质作用const修饰成员函数的隐式this指针,将其类型从类名* const this(仅指向不可改)变为const 类名* const this(指向和指向的内容均不可改),因此 const 成员函数内无法修改类的任何成员变量。

调用规则:const 对象仅能调用 const 成员函数,普通对象可调用 const / 普通成员函数(权限缩小允许);仅读取成员的函数建议定义为 const,提升代码兼容性。

特殊限制:构造、析构函数因需修改对象(初始化 / 清理资源),无法定义为 const 成员函数。

7.3 实现示例

复制代码
#include<iostream>
using namespace std;

class Date
{
public:
    Date(int year = 1, int month = 1, int day = 1)
        : _year(year), _month(month), _day(day) {}
    // const成员函数:仅读取,不修改
    void Print() const
    {
        // _year = 2025; // 编译报错:const成员函数不能修改成员
        cout << _year << "/" << _month << "/" << _day << endl;
    }
    // 普通成员函数:可修改成员
    void SetDay(int day)
    {
        _day = day;
    }
private:
    int _year, _month, _day;
};

int main()
{
    const Date d1(2025,8,1); // const对象
    d1.Print(); // 正确:const对象调用const成员函数
    // d1.SetDay(2); // 编译报错:const对象不能调用普通成员函数

    Date d2(2025,8,2); // 普通对象
    d2.Print(); // 正确:普通对象调用const成员函数
    d2.SetDay(3); // 正确:普通对象调用普通成员函数
    return 0;
}

八、取地址运算符重载

取地址运算符重载包含普通取地址const 取地址 两个版本,属于默认成员函数,编译器自动生成的版本完全满足需求,极少需要手动实现。

8.1 语法格式

复制代码
class Date
{
public:
    // 普通取地址运算符重载:返回普通对象的地址
    Date* operator&()
    {
        return this; // 编译器默认行为,返回对象自身地址
        // 特殊场景:return nullptr; // 故意返回空地址,禁止外部取地址
    }
    // const取地址运算符重载:返回const对象的地址
    const Date* operator&() const
    {
        return this; // 编译器默认行为
    }
private:
    int _year, _month, _day;
};

8.2 注意

  1. 手动实现的唯一场景:禁止外部获取对象的真实地址(如故意返回 nullptr);
  2. 普通对象调用operator&(),const 对象调用operator&() const(权限匹配);
  3. 日常开发中,直接使用编译器默认生成的版本,无需手动实现。

核心总结

  1. 默认成员函数是 C++ 封装的核心,编译器会为空类生成 6 个,重点掌握前 4 个(构造、析构、拷贝构造、赋值重载);
  2. 构造 / 析构:自动完成初始化 / 资源清理,替代 C 语言的手动 Init/Destroy,有堆资源的类必须手动实现析构;
  3. 浅拷贝 / 深拷贝:无堆资源的类(如 Date)用编译器默认的浅拷贝即可;有堆资源的类(如 Stack)必须手动实现深拷贝的拷贝构造和赋值重载,避免浅拷贝的问题;
  4. 运算符重载 :让自定义类型支持内置类型的运算符,必须至少有一个类类型参数,5 个运算符不能重载,<</>>建议重载为全局函数,++/--通过 int 形参区分前置 / 后置;
  5. const 成员函数:修饰 this 指针,禁止修改成员变量,const 对象只能调用 const 成员函数,只读函数建议定义为 const;
  6. 拷贝构造与赋值重载 :核心区分是对象是否已存在,初始化新对象用拷贝构造,已存在对象赋值用赋值重载。

下一篇再见🤠

相关推荐
寻寻觅觅☆6 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
时代的凡人7 小时前
0208晨间笔记
笔记
fpcc7 小时前
并行编程实战——CUDA编程的Parallel Task类型
c++·cuda
今天只学一颗糖7 小时前
1、《深入理解计算机系统》--计算机系统介绍
linux·笔记·学习·系统架构
testpassportcn8 小时前
AWS DOP-C02 認證完整解析|AWS DevOps Engineer Professional 考試
网络·学习·改行学it
ceclar1238 小时前
C++使用format
开发语言·c++·算法
lanhuazui108 小时前
C++ 中什么时候用::(作用域解析运算符)
c++
charlee448 小时前
从零实现一个生产级 RAG 语义搜索系统:C++ + ONNX + FAISS 实战
c++·faiss·onnx·rag·语义搜索
老约家的可汗9 小时前
初识C++
开发语言·c++
crescent_悦9 小时前
C++:Product of Polynomials
开发语言·c++