C++自定义类型默认值和构造技巧有哪些

来源:草根站长作者:零壳头衔:程序员
导读:本期聚焦于小伙伴创作的《C++自定义类型默认值和构造技巧有哪些》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++自定义类型默认值和构造技巧有哪些》有用,将其分享出去将是对创作者最好的鼓励。

在C++编程中,自定义类型比如结构体、类的默认值设置和构造逻辑直接关系到程序的运行稳定性,不少运行时错误都源于自定义类型实例未正确初始化。理解默认值的生成规则和构造技巧,能有效减少这类问题。

C++自定义类型默认值和构造技巧有哪些

C++自定义类型的默认行为

当我们定义一个自定义类型后,如果没有显式定义构造函数,编译器会自动生成一个默认构造函数。这个默认构造函数的行为会根据类型的成员不同而有所区别。

内置类型成员的默认初始化

如果自定义类型包含内置类型成员(比如int、double、指针等),使用编译器生成的默认构造函数创建实例时,这些内置类型成员不会被默认初始化,其值是未定义的,也就是垃圾值。

#include <iostream>

struct Student {
    int age;
    double score;
};

int main() {
    Student s1; // 使用编译器生成的默认构造函数
    // 此时s1.age和s1.score的值是未定义的,输出结果不可预期
    std::cout << s1.age << std::endl;
    std::cout << s1.score << std::endl;
    return 0;
}

类类型成员的默认初始化

如果自定义类型的成员是其他类类型,且该类型有默认构造函数,那么编译器生成的默认构造函数会调用这些成员的默认构造函数完成初始化。

#include <iostream>
#include <string>

struct Person {
    std::string name; // std::string有默认构造函数,会初始化为空字符串
    int id; // 内置类型,未定义初始值
};

int main() {
    Person p1;
    std::cout << p1.name << std::endl; // 输出空字符串,因为string默认构造初始化了
    std::cout << p1.id << std::endl; // 输出未定义的值
    return 0;
}

设置自定义类型默认值的常用方法

类内初始值

C++11之后支持在自定义类型的成员声明时直接赋予初始值,也就是类内初始值。当创建实例时,如果没有通过构造函数显式初始化该成员,就会使用这个默认值。

#include <iostream>

struct Product {
    int price = 0; // 类内初始值,默认值为0
    std::string name = "unknown"; // 类内初始值,默认值为unknown
};

int main() {
    Product p1;
    std::cout << p1.price << std::endl; // 输出0
    std::cout << p1.name << std::endl; // 输出unknown
    return 0;
}

自定义默认构造函数

我们可以显式定义默认构造函数,在函数体内为成员赋值,或者在初始化列表中设置默认值,这样创建实例时就会按照我们设定的逻辑初始化。

#include <iostream>

class User {
private:
    int level;
    std::string role;
public:
    // 自定义默认构造函数,初始化列表设置默认值
    User() : level(1), role("normal") {}
    
    void printInfo() {
        std::cout << "level: " << level << ", role: " << role << std::endl;
    }
};

int main() {
    User u1;
    u1.printInfo(); // 输出level: 1, role: normal
    return 0;
}

实用的构造技巧

委托构造函数

C++11引入的委托构造函数可以让一个构造函数调用同一个类的其他构造函数,减少重复代码。比如我们可以定义一个全参数构造函数,然后让默认构造函数委托它完成初始化。

#include <iostream>

class Point {
private:
    int x;
    int y;
public:
    // 全参数构造函数
    Point(int xVal, int yVal) : x(xVal), y(yVal) {}
    // 委托构造函数,委托给全参数构造函数,默认x和y为0
    Point() : Point(0, 0) {}
    
    void print() {
        std::cout << "x: " << x << ", y: " << y << std::endl;
    }
};

int main() {
    Point p1;
    p1.print(); // 输出x: 0, y: 0
    Point p2(3, 4);
    p2.print(); // 输出x: 3, y: 4
    return 0;
}

拷贝构造与移动构造的合理定义

当自定义类型需要管理资源(比如动态内存)时,需要合理定义拷贝构造函数和移动构造函数,避免浅拷贝带来的资源重复释放问题,同时提升资源转移的效率。

#include <iostream>
#include <cstring>

class MyString {
private:
    char* data;
    int length;
public:
    // 构造函数
    MyString(const char* str = "") {
        length = std::strlen(str);
        data = new char[length + 1];
        std::strcpy(data, str);
    }
    
    // 拷贝构造函数,深拷贝
    MyString(const MyString& other) {
        length = other.length;
        data = new char[length + 1];
        std::strcpy(data, other.data);
    }
    
    // 移动构造函数
    MyString(MyString&& other) noexcept : data(other.data), length(other.length) {
        other.data = nullptr;
        other.length = 0;
    }
    
    ~MyString() {
        delete[] data;
    }
    
    void print() {
        if (data) {
            std::cout << data << std::endl;
        }
    }
};

int main() {
    MyString s1("hello");
    MyString s2 = s1; // 调用拷贝构造函数
    s2.print(); // 输出hello
    MyString s3 = std::move(s1); // 调用移动构造函数
    s3.print(); // 输出hello
    return 0;
}

explicit关键字避免隐式转换

如果构造函数只有一个参数,编译器可能会进行隐式转换,有时候这会带来不符合预期的结果。使用explicit关键字修饰构造函数,可以禁止这种隐式转换,让代码更清晰安全。

#include <iostream>

class Number {
private:
    int val;
public:
    // 使用explicit修饰,禁止隐式转换
    explicit Number(int v) : val(v) {}
    int getVal() const { return val; }
};

void printNumber(const Number& n) {
    std::cout << n.getVal() << std::endl;
}

int main() {
    Number n1(10); // 正确,显式构造
    printNumber(n1); // 正确
    // printNumber(10); // 错误,无法隐式转换int为Number
    return 0;
}

注意事项

在使用自定义类型时,要注意区分内置类型和类类型的初始化规则,优先使用类内初始值或者显式构造函数设置默认值,避免依赖未定义的初始值。另外,当自定义类型涉及资源管理时,一定要遵循三五法则,合理定义构造、拷贝、移动、析构相关函数,防止资源泄漏或者重复释放的问题。

C++自定义类型默认值构造技巧构造函数修改时间:2026-07-03 02:06:36

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。