到底要不要使用 = default 声明默认构造函数?

两种情况对比

情况1:使用类内初始化,不写默认构造函数

class Rectangle {
private:
    double width {1.0};
    double height {1.0};
    std::string name {"Rectangle"};

public:
    // 没有声明默认构造函数
    // 编译器会自动生成一个
    
    Rectangle(double w, double h, const std::string& n) 
        : width(w), height(h), name(n) {
    }
    
    void print() {
        std::cout << name << ": " << width << " x " << height << std::endl;
    }
};

情况2:使用类内初始化,显式写 = default

class Rectangle {
private:
    double width {1.0};
    double height {1.0};
    std::string name {"Rectangle"};

public:
    Rectangle() = default;  // 显式要求编译器生成默认构造函数
    
    Rectangle(double w, double h, const std::string& n) 
        : width(w), height(h), name(n) {
    }
    
    void print() {
        std::cout << name << ": " << width << " x " << height << std::endl;
    }
};

关键区别

不写默认构造函数时:

  • 编译器会自动生成一个默认构造函数
  • 这个自动生成的构造函数会使用类内初始值来初始化成员变量
  • 可以正常创建对象:Rectangle rect;

显式写 = default 时:

  • 效果与编译器自动生成的完全相同
  • 只是更明确地表达了设计意图

实际测试

#include <iostream>
#include <string>

class RectangleA {
private:
    double width {1.0};
    double height {1.0};
    std::string name {"Rectangle"};
public:
    // 没有默认构造函数声明
    void print() {
        std::cout << name << ": " << width << " x " << height << std::endl;
    }
};

class RectangleB {
private:
    double width {1.0};
    double height {1.0};
    std::string name {"Rectangle"};
public:
    RectangleB() = default;  // 显式默认
    void print() {
        std::cout << name << ": " << width << " x " << height << std::endl;
    }
};

int main() {
    RectangleA rect1;  // 正常工作!使用类内初始值
    RectangleB rect2;  // 正常工作!使用类内初始值
    
    rect1.print();  // 输出: Rectangle: 1 x 1
    rect2.print();  // 输出: Rectangle: 1 x 1
    
    return 0;
}

什么时候需要显式写 = default

在以下几种情况下需要:

1. 有其他构造函数时

class Rectangle {
private:
    double width {1.0};
    double height {1.0};
public:
    // 如果只有这个构造函数,默认构造函数不会被自动生成
    Rectangle(double w, double h) : width(w), height(h) {}
    
    // 需要显式要求编译器生成默认构造函数
    Rectangle() = default;
};

2. 需要明确的代码文档

class Rectangle {
private:
    double width {1.0};
    double height {1.0};
public:
    Rectangle() = default;  // 明确表示:我需要默认构造函数
    
    // 其他代码...
};

3. 在头文件中显式定义,在源文件中实现特殊逻辑

// .h 文件
class Rectangle {
private:
    double width {1.0};
    double height {1.0};
public:
    Rectangle();  // 声明但不 = default
};

// .cpp 文件
Rectangle::Rectangle() {
    // 可能有一些特殊的初始化逻辑
    std::cout << "Rectangle created with default values" << std::endl;
}

总结

  • 不写默认构造函数:编译器自动生成,使用类内初始值 ✅
  • = default:效果相同,但更明确意图 ✅
  • 只有在有其他构造函数时,才需要显式写 = default 来保留默认构造函数
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐