Static和const理解

1.类内const成员和static成员(2024.04.20)

conststaticstatic const
储存在哪?堆区静态区域静态区域
初始化应注意列表初始化?类外初始化声明时必须初始化
所有者对象
是否可改变不可可改变不可

1.1 类内const成员:必须在初始化列表中初始化
  • 1.1.1 构造函数各部分说明:初始化列表作用是初始化,构造函数体作用是赋值(和其他逻辑处理)。
    所以const成员只能在初始化列表中初始化;如果在初始化列表没有显示初始化,则会执行默认初始化,如果再在函数体中赋值,则违背了const使用目的(初始化后值不能改变)。
  • 1.1.2 引申"类型是类成员在不同位置的调用过程":初始化列表作用直接调用拷贝构造函数;构造函数体中则先调用相应传入参数的默认构造、再调用该类的拷贝构造函数或拷贝赋值运算符【相应知识点:C++ Primmer第13章】;
    所以数据密集型的类来说,使用初始化列表会提高效率,以下为示例:
#include <iostream>
 
using namespace std;
 
class Test1
{
public:
    Test1() {cout << "Construct Test1" << endl ;} // 无参构造函数
    Test1(const Test1& t1) // 拷贝构造函数
    {
        cout << "Copy constructor for Test1" << endl ;this->a = t1.a ;
    }
    Test1& operator = (const Test1& t1) // 重载赋值运算符(也称为重载赋值函数)
    {
        cout << "assignment for Test1" << endl ;
        this->a = t1.a ;
        return *this;
    }
private:
    int a ;
};
 
class Test2
{
public:
    Test1 test1; //此处第二次调用Test 1的construct;
    //std::cout<<"进入Test2 的构造函数"<<std::endl; //类中只能包含成员变量和成员函数!
    Test2(Test1 &t1){test1 = t1 ;} //此处的“=”调用重载的“=”操作符;
};
 
int main(){
    Test1 t1; //此处第一次调用Test1的construct;
    cout<<"end of fist construct t1"<<endl;
    Test2 t2(t1);
}

输出

Construct Test1
end of fist construct t1
Construct Test1
assignment for Test1

解释:main函数中,Test2 t2(t1)会首先调用Test2的拷贝构造函数Test2(Test1 &t1){test1 = t1},由于该构造函数没有初始化列表,所以对于t2中的成员test1,会通过调用Test1的无参构造函数生成成员对象test1,然后再通过重载赋值运算符对参数t1进行拷贝test1 = t1。

初始化列表一般是直接初始化,另外其他初始化方式还有默认初始化、拷贝初始化,参考链接

  • 1.1.3 误区解释:为什么以下代码不对
class A{const int a = 1;};

解释:定义class的时候不能够对其中的成员变量赋值,因为定义一个class并不会为这个class分配空间,是只有在instance class时候才会分配空间,既然没有空间,当然不能赋值。

改成下面就对了

class A {  
public:  
    const int a;  
  
    A() : a(1) {} // 在构造函数初始化列表中初始化const成员变量a  
};

其他说明:

  • 如果想要一个const成员变量并且在类定义时就给它一个固定的值,同时确保这个值在类的所有实例中都是相同的,那么可以考虑使用static const成员变量,但即使在这种情况下,您也需要在类定义外部进行定义(而不是初始化)。
  • const声明变量需要在初始化列表中初始化。(还未对其他初始化方式测试,待学习)
    参考引用来源(学习记录使用,如有侵权,请联系删除)
1.2类内Static成员:必须在类外部定义(初始化)

解释:类内的static成员是类级别的变量,而不是对象级别的。这意味着无论创建了多少个类的实例,都只有一个static成员变量存在,故在类外初始化,示例如下。

// MyClass.h  
class MyClass {  
public:  
    static int myStaticMember; // 声明static成员  
  
    // ...  
};  
  
// MyClass.cpp  
#include "MyClass.h"  
  
int MyClass::myStaticMember = 0; // 定义并初始化static成员
1.3static const
  • static const整型成员(以及枚举类型)有一个特例,它们可以在类定义内部进行初始化;对于非整型static const成员,仍然需要在类外部定义和初始化。
class MyClass {  
public:  
    static const int myStaticConstMember = 42; // 声明并初始化static const整型成员  
  
    // ...  
};
2.const(2022.06.04)

关于const,参考C++Primmer 2.4.1节

代码如下

#include <iostream>
using namespace std;

int main()
{
    int i1 = 5;
    int& r1 = i1;
    i1 = 10;
    cout << "i1 " << i1 << " r1 " << r1 << endl;
    r1 = 20;
    cout << "i1 " << i1 << " r1 " << r1 << endl;

    const int i2 = 50;
    const int& r2 = i2;
    cout << "i2 " << i2 << " r2 " << r2 << endl;
    
    int i3 = 3;
    const int& r3 = i3;
    i3 = 30;
    //r3 = 40;   这里会报错"左值必须为可修改的表达式",所以常量不可修改
    cout << "i3 " << i3 << " r3 " << r3 << endl;

    const int i4 = 4;  // 这里如果没有对i4进行初始值设定会报错:常量 变量 i4需要初始设定值
    //int& r4 = i4;     // 会报错,所以无法将非const引用绑定到const对象 
    cin.get();
    return 0;
}

输出
在这里插入图片描述
变量地址
在这里插入图片描述

有个疑问哈:r3本身不可改变,但是r3可以通过i3间接改变值,有什么应用场景吗?

3.const修饰函数参数
#例如
void function(const string& s){...}

这种通过引用传递(相对于值传递),也就是形参s与实参是同一个参数(地址相同),const表明不会改变参数的值。

我有个疑问哈,请各位大佬解惑一下:如果不加&,仅仅是const string修饰,有什么用途吗?应用场景是什么?

#例如
void function(const string s){...}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值