问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

深入理解C++中的const成员

创作时间:
作者:
@小白创作中心

深入理解C++中的const成员

引用
CSDN
1.
https://blog.csdn.net/yishaobai/article/details/146000672

在C++编程中,const成员是类型系统的重要组成部分,尤其在类成员的设计中扮演关键角色。通过合理使用const成员,开发者可以显著提升代码的健壮性、可维护性和安全性。本文将深入探讨const成员函数、const成员变量的核心特性和应用场景。

1、const成员函数

1.1 基础语法

class A {
public:
    void constFunc() const { // const成员函数
        std::cout << "constFunc" << std::endl;
    }
    void nonConstFunc() { // 普通成员函数
        std::cout << "nonConstFunc" << std::endl;
    }
};

1.2 核心特性

  • 不可变性保证:禁止修改类的非mutable成员变量。
  • 对象类型适配
class A {
public:
    void constFunc() const {
        std::cout << "constFunc" << std::endl;
    }
    void nonConstFunc() {
        std::cout << "nonConstFunc" << std::endl;
    }
};
int main() {
    const A a;
    a.nonConstFunc(); // 编译错误,权限的放大
    a.constFunc(); // 合法
    return 0;
}
  • 重载机制
class Vector {
public:
    Vector(int n = 5) {
        a_ = new int[n];
        size_ = 0;
        capacity_ = n;
    }
    void PushBack(int val) {
        if (size_ == capacity_) {
            capacity_ *= 2;
            int* tmp = new int[capacity_];
            for (int i = 0; i < size_; i++) {
                tmp[i] = a_[i];
            }
            delete[] a_;
            a_ = tmp;
        }
        a_[size_] = val;
        size_++;
    }
    int Size() const {
        return size_;
    }
    ~Vector() {
        delete[] a_;
        size_ = capacity_ = 0;
    }
    
    int& operator[](int index) {
        return a_[index];
    }
    const int& operator[](int index) const {
        return a_[index];
    }
    
private:
    int* a_;
    int size_;
    int capacity_;
};
void PrintVector(const Vector& vec) {
    for (int i = 0; i < vec.Size(); ++i) {
        std::cout << vec[i] << " "; // 匹配const的成员函数
    }
    std::cout << std::endl;
}
int main() {
    Vector v;
    v.PushBack(1);
    v.PushBack(2);
    v.PushBack(3);
    v.PushBack(4);
    v.PushBack(5);
    v.PushBack(6);
    PrintVector(v);
    for (int i = 0; i < v.Size(); ++i) {
        std::cout << ++v[i] << " "; // 匹配非const的成员函数
    }
    return 0;
}

1.3 典型应用场景

  • 访问器方法(getter)。
  • 数据完整性检查。
  • 对象状态查询。
  • 支持常量对象操作。

2、const成员变量

2.1 非静态const成员

class A {
public:
    A()
        : a_(1), b_(2) // 初始化列表
    {}
private:
    const int a_; // const成员变量必须在声明的时候初始化,因此必须采用初始化列表方式初始化或给缺省值。
    int b_;
};
int main() {
    A a;
    return 0;
}

2.2 静态const成员

class A {
public:
    A() {
        b_ = 2;
    }
private:
    static const int a_; // 声明
    int b_;
};
const int A::a_ = 1; // 定义
int main() {
    A a;
    return 0;
}

3、mutable成员变量

3.1 打破const限制

class Cache {
    mutable std::mutex mtx;         // 可变同步原语
    mutable std::vector<int> cached; // 可变缓存
public:
    void updateCache() const {
        std::lock_guard<std::mutex> lock(mtx);
        // 即使const函数也可修改cached
    }
};

3.2 使用场景

  • 线程同步原语。
  • 缓存数据。
  • 引用计数。
  • 调试统计信息。

4、深入初始化规则

4.1 必须使用初始化列表的情况

成员类型
初始化方式
const成员
必须使用初始化列表
引用成员
必须使用初始化列表
无默认构造的对象
必须使用初始化列表

4.2 初始化顺序问题

class A {
public:
    A(int x)
        : b_(x), a_(b_)
    {}
private:
    int a_; 
    int b_;
};
int main() {
    A a(3);
    return 0;
}
  • 由此可见,初始化顺序是按照声明的顺序决定的。

5、总结

合理运用const成员能够:

  • 减少约30%的对象状态错误。
  • 提升接口设计的清晰度。
  • 增强多线程环境下的安全性。
  • 帮助编译器生成更优化的代码。
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号