这里的const是起了个什么作用呢? void Enter () const;

博客展示了C++中CSync类的代码,包含构造、析构等函数。作者对Enter()和Leave()函数后的const关键字作用存疑,通过在函数体添加赋值语句报错,去除const错误消失,证明const有限制作用,但仍不清楚其具体含义和作用,寻求参考依据。

 

//sync.h

class CSync 

{

       HANDLE m_sync;

public:

       CSync();

       virtual ~CSync();

       CSync (CSync& s);

       CSync& operator= (CSync& s);

       void Enter () const;

       void Leave () const;

};

 

//sync.cpp

CSync::CSync ()

{

       m_sync = CreateMutex (NULL, false, NULL);

       if (m_sync == NULL)

              throw CError (1001);

}

 

CSync::~CSync()

{

       if (m_sync != NULL)

       {

              CloseHandle (m_sync);

              m_sync = NULL;

       }

}

 

void CSync::Enter () const

{

       WaitForSingleObject (m_sync, INFINITE);

}

 

void CSync::Leave () const

{

       ReleaseMutex (m_sync);

}

 

里面的Enter()Leave()后面多了个const,本来不太明白是什么作用后来尝试在Enter()Leave()的函数体里增加一个BOOL的赋值语句时被提示: error C2166: l-value specifies const object 于是猜想这个const导致了这个问题出现的,它可能限制了函数里只能做一个简单的调用,后来去除const关键字后错误消失,证明了我的猜想,但是还是不明白这个const在这里的具体含义和作用,不知道哪位大虾能找到一些可以参考的根据呢?

在代码中,`const char*` 和 `const uint8_t` 的使用差异主要源于它们的语义角色和实际用途。以下是具体分析: --- ### **1. 参数列表使用 `const char*` 的原因** - **语义明确**: `package_name`、`app_name` 和 `play_state` 是字符串(如 `"com.example.music"`),C/C++ 中字符串通常用 `const char*` 表示(指向只读字符数组的指针)。 - `const` 修饰符表示函数不会修改这些字符串的内容,符合只读语义。 - 如果尝试通过指针修改字符串内容,编译器会报错(如 `*(package_name + 0) = 'A';` 会触发错误)。 - **安全性**: 使用 `const char*` 可以避免函数内部意外修改外部字符串,增强代码健壮性。 --- ### **2. `strcpy_max_len` 使用 `const uint8_t` 的原因** - **数值语义**: `strcpy_max_len` 表示**字符串拷贝的最大长度**(如 `entry[0].value` 的缓冲区大小减 1),是一个纯数值,与字符或指针无关。 - `uint8_t` 是无符号 8 位整数(范围 0~255),适合表示长度、偏移量等小范围数值。 - `const` 修饰符表示该值在运行时不可修改(编译期常量或只读变量)。 - **内存效率**: `uint8_t` 仅占用 1 字节,而 `int` 或 `size_t` 可能占用 4 字节(取决于平台)。在资源受限的嵌入式系统中,使用 `uint8_t` 可以节省栈空间。 --- ### **3. 关键区别总结** | 特性 | `const char*` 参数 | `const uint8_t` 变量 | |---------------------|----------------------------------|------------------------------------| | **类型** | 指针(指向字符) | 整数(表示长度) | | **用途** | 传递字符串数据 | 限制字符串拷贝的边界 | | **`const` 的作用** | 禁止修改指针指向的数据 | 禁止修改变量值(运行时) | | **内存占用** | 指针大小(通常 4/8 字节) | 1 字节(`uint8_t`) | --- ### **4. 为什么不用 `const int` 或 `const size_t`?** - **平台适配性**: `uint8_t` 明确表示 8 位无符号整数,而 `int` 的大小可能因平台而异(16/32/64 位)。在需要精确控制内存的场景(如嵌入式系统),`uint8_t` 更可靠。 - **语义清晰**: `strcpy_max_len` 的值通常较小(如缓冲区大小 `32`),用 `uint8_t` 足以覆盖,且能避免隐式类型转换的风险。 --- ### **5. 潜在问题与改进建议** #### **问题 1:`uint8_t` 可能溢出** 如果缓冲区大小超过 255,`uint8_t` 会溢出。此时应改用 `size_t` 或 `uint16_t`: ```c const size_t strcpy_max_len = sizeof(entry[0].value) - 1; // 更通用的写法 ``` #### **问题 2:`const` 的局限性** - `const uint8_t` 仅保证变量本身不可修改,但无法保证 `sizeof(entry[0].value)` 的计算结果不被修改(因为 `entry` 可能是动态数组)。 - 更安全的做法是使用宏定义或枚举: ```c #define STRCPY_MAX_LEN (sizeof(entry[0].value) - 1) ``` #### **问题 3:硬编码数组大小** `UserEvent_t_ValuesEntry entry[5]` 中的 `5` 是硬编码的,容易出错。建议改用宏或动态分配: ```c #define MAX_EVENT_PARAMS 5 UserEvent_t_ValuesEntry entry[MAX_EVENT_PARAMS]; ``` --- ### **6. 完整改进示例** ```c #define MAX_EVENT_PARAMS 5 #define STRCPY_MAX_LEN(field) (sizeof((field)) - 1) void music_app_enter_event_point(const char *package_name, const char *app_name, bool source, const char *play_state) { if (!package_name || !app_name || !play_state) { OPLUS_UI_ERROR_LOG("[music_app] Invalid arguments\n"); return; } UserEvent_t_ValuesEntry entry[MAX_EVENT_PARAMS]; memset(entry, 0, sizeof(entry)); // 使用宏计算最大长度,避免硬编码 strncpy(entry[0].key, "package_name", STRCPY_MAX_LEN(entry[0].key)); strncpy(entry[0].value, package_name, STRCPY_MAX_LEN(entry[0].value)); // ...(其他参数填充类似)... service_eventpoint_log("30412010", "music_app_enter", MAX_EVENT_PARAMS, entry, true, true); } ``` --- ### **关键点总结** - **`const char*`**:用于只读字符串参数,明确语义并防止意外修改。 - **`const uint8_t`**:用于小范围数值常量,节省内存且类型明确。 - **改进方向**:使用宏或枚举替代硬编码,增强可维护性和安全性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值