【漫游C++11】nullptr与std::nullptr_t

本文详细解释了C++中NULL和nullptr的区别,NULL在C++中被定义为0,可能导致误解,而nullptr则是一个专门用于表示空指针的类型,能有效避免这种误解。文章还提供了一个不支持C++11编译器模拟nullptr的方法。

在C/C++中,有一个常用的宏:NULL。在C语言中,一般定义为((void*)0),也允许定义成0,在C++中,NULL必须是0。

即:

#ifndef NULL
    #ifdef __cplusplus
        #define NULL 0             // C++
    #else
        #define NULL ((void *)0)   // C语言的通常定义      现在的C语言(C99)现在已经支持用“//”注释
    #endif
#endif

这样的定义,一不留神就会引起误解:

void Func(char*)
{
    std::cout << "Func(char*)" << std::endl;
}

void Func(int)
{
    std::cout << "Func(int)" << std::endl;
}

int main()
{
    Func(NULL); // Func(int)
    return 0;
}

由于我们经常用NULL表示空指针,所以上面的代码容易被误认为是调用第一个Func,但实际上,由于NULL在C++中是0,所以调用了第二个。

在头脑清醒的时候,这不是什么问题,但随着代码量的增加,我们很难把注意力集中到这个细节上,就算注意到了这个问题,它也会成为不必要的心智负担。

nullptr应运而生。

nullptr是std::nullptr_t类型的(constexpr)变量。std::nullptr_t可以显式或隐式地转换为任何指针(包括类的成员函数指针),但不能显式或隐式地转换为任何其他类型。


使用nullptr可以消除这个误会,例如,上面的代码,调用Func(nullptr)一定输出Func(char*)。


其实,C++11将NULL重新定义效果会更好一些,但可能是考虑到已经有太多的代码用了NULL,为了使得以前的代码仍任可用,所以才新增的nullptr吧。


最后,补充一些细节:

1)std::nullptr_t不能用于算术表达式,即,不能+、-、*等;

2)std::nullptr_t可以用于关系表达式,两个std::nullptr_t类型的变量,进行==、<=、>=运算都会返回true,其他的关系运算返回false;

3)nullptr不能进行&(取地址)运算。


如果你的编译器不支持C++11,可以用C++98/C++03模拟一个nullptr:

// 不支持C++11的编译器
class nullptr_tt
{
public:
    template<class _Tx> operator _Tx*() const { return 0; }
    template<class _Tx, class _Ty> operator _Ty _Tx::*() const{ return 0; }
private:
    void operator& () const; // 不允许取地址
};

const nullptr_tt nullptr;

转载于:https://my.oschina.net/jthmath/blog/539845

#include <esp_wifi.h> #include <esp_event.h> #include <esp_log.h> #include <esp_timer.h> #include <esp_sleep.h> // 状态枚举 enum class WifiState { INIT, // 初始化 SCANNING, // AP扫描 AUTHENTICATING, // 认证中 ASSOCIATING, // 关联中 CONNECTED, // 已连接 DISCONNECTED, // 断开连接 ROAMING_SCAN, // 漫游扫描 ROAMING_AUTH, // 漫游认证 ROAMING_ASSOC, // 漫游关联 LIGHT_SLEEP, // 轻睡眠模式 DEEP_SLEEP // 深睡眠模式 }; // 事件枚举 enum class WifiEvent { SCAN_COMPLETE, // 扫描完成 AUTH_REQ, // 认证请求 AUTH_RESP, // 认证响应 ASSOC_REQ, // 关联请求 ASSOC_RESP, // 关联响应 CONNECTED, // 连接成功 DISCONNECTED, // 连接断开 ROAM_TRIGGER, // 漫游触发 BEACON_LOST, // 信标丢失 SLEEP_ENTER, // 进入睡眠 WAKE_UP // 唤醒事件 }; class WiFiStateMachine { private: // 当前状态 WifiState currentState = WifiState::INIT; // 状态转移表(状态 -> 事件 -> 新状态) std::map<WifiState, std::map<WifiEvent, WifiState>> transitionTable = { {WifiState::INIT, { {WifiEvent::SCAN_COMPLETE, WifiState::SCANNING} }}, {WifiState::SCANNING, { {WifiEvent::AUTH_REQ, WifiState::AUTHENTICATING} }}, {WifiState::AUTHENTICATING, { {WifiEvent::AUTH_RESP, WifiState::ASSOCIATING}, {WifiEvent::DISCONNECTED, WifiState::DISCONNECTED} }}, {WifiState::ASSOCIATING, { {WifiEvent::ASSOC_RESP, WifiState::CONNECTED}, {WifiEvent::DISCONNECTED, WifiState::DISCONNECTED} }}, {WifiState::CONNECTED, { {WifiEvent::DISCONNECTED, WifiState::DISCONNECTED}, {WifiEvent::ROAM_TRIGGER, WifiState::ROAMING_SCAN}, {WifiEvent::SLEEP_ENTER, WifiState::LIGHT_SLEEP} }}, {WifiState::ROAMING_SCAN, { {WifiEvent::AUTH_REQ, WifiState::ROAMING_AUTH} }}, {WifiState::ROAMING_AUTH, { {WifiEvent::AUTH_RESP, WifiState::ROAMING_ASSOC} }}, {WifiState::ROAMING_ASSOC, { {WifiEvent::ASSOC_RESP, WifiState::CONNECTED} }}, {WifiState::LIGHT_SLEEP, { {WifiEvent::WAKE_UP, WifiState::CONNECTED}, {WifiEvent::BEACON_LOST, WifiState::SCANNING} }} }; // 低功耗配置参数 struct { int beacon_interval = 5000; // 默认信标监测间隔(ms) int sleep_delay = 300; // 进入休眠等待时间(s) int roam_threshold = -75; // 漫游触发RSSI阈值(dBm) int roam_scan_duration = 100; // 漫游扫描时长(ms) } powerConfig; // 连接稳定性计数器 int stableCounter = 0; const int STABLE_THRESHOLD = 5; // 连续稳定计数阈值 // 定时器句柄 esp_timer_handle_t beacon_timer; esp_timer_handle_t sleep_timer; /** * 处理状态转移 * @param event 触发事件 */ void handleEvent(WifiEvent event) { auto stateTransitions = transitionTable.find(currentState); if (stateTransitions != transitionTable.end()) { auto newState = stateTransitions->second.find(event); if (newState != stateTransitions->second.end()) { // 执行状态转移前的清理 exitStateActions(currentState); // 更新状态 currentState = newState->second; ESP_LOGI("StateMachine", "Transition: %s -> %s", stateToString(currentState).c_str(), stateToString(newState->second).c_str()); // 执行新状态的入口动作 enterStateActions(newState->second); } } } /** * 状态退出动作 * @param state 退出的状态 */ void exitStateActions(WifiState state) { switch(state) { case WifiState::SCANNING: esp_timer_stop(beacon_timer); break; case WifiState::LIGHT_SLEEP: // 唤醒后恢复活动 esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER); break; default: break; } } /** * 状态进入动作 * @param state 进入的状态 */ void enterStateActions(WifiState state) { switch(state) { case WifiState::SCANNING: startScan(); break; case WifiState::AUTHENTICATING: sendAuthRequest(); break; case WifiState::CONNECTED: startBeaconMonitoring(); checkConnectionStability(); break; case WifiState::ROAMING_SCAN: startRoamScan(); break; case WifiState::LIGHT_SLEEP: enterLightSleep(); break; default: break; } } /** * 启动AP扫描 */ void startScan() { wifi_scan_config_t scan_config = { .ssid = nullptr, .bssid = nullptr, .channel = 0, .show_hidden = true, .scan_type = WIFI_SCAN_TYPE_ACTIVE, .scan_time = { .active = 120 } // 120ms主动扫描 }; ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, false)); } /** * 启动低功耗漫游扫描 */ void startRoamScan() { wifi_scan_config_t scan_config = { .scan_type = WIFI_SCAN_TYPE_PASSIVE, // 被动扫描省电 .scan_time = { .passive = powerConfig.roam_scan_duration } }; ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, false)); } /** * 进入轻睡眠模式(ESP32优化) */ void enterLightSleep() { // 配置唤醒源 esp_sleep_enable_timer_wakeup(powerConfig.sleep_delay * 1000000); esp_sleep_enable_wifi_wakeup(); // 保存当前状态 WifiState preSleepState = currentState; // 进入轻睡眠(保留WiFi连接) esp_light_sleep_start(); // 唤醒后恢复状态 currentState = preSleepState; handleEvent(WifiEvent::WAKE_UP); } /** * 动态调整信标监测周期 */ void adjustBeaconMonitoring() { // 获取当前信号强度 wifi_ap_record_t ap_info; esp_wifi_sta_get_ap_info(&ap_info); int8_t rssi = ap_info.rssi; // 根据信号质量调整监测频率 if (rssi > -60) { // 强信号 powerConfig.beacon_interval = 10000; // 10秒 stableCounter++; } else if (rssi > -70) { // 中等信号 powerConfig.beacon_interval = 5000; // 5秒 stableCounter = 0; } else { // 弱信号 powerConfig.beacon_interval = 2000; // 2秒 stableCounter = 0; } // 重启定时器 esp_timer_stop(beacon_timer); esp_timer_start_periodic(beacon_timer, powerConfig.beacon_interval * 1000); } /** * 检查连接稳定性 */ void checkConnectionStability() { if (stableCounter >= STABLE_THRESHOLD) { handleEvent(WifiEvent::SLEEP_ENTER); } } /** * 状态转字符串(调试用) */ std::string stateToString(WifiState state) { const std::map<WifiState, std::string> stateMap = { {WifiState::INIT, "INIT"}, {WifiState::SCANNING, "SCANNING"}, {WifiState::AUTHENTICATING, "AUTHENTICATING"}, {WifiState::ASSOCIATING, "ASSOCIATING"}, {WifiState::CONNECTED, "CONNECTED"}, {WifiState::DISCONNECTED, "DISCONNECTED"}, {WifiState::ROAMING_SCAN, "ROAMING_SCAN"}, {WifiState::ROAMING_AUTH, "ROAMING_AUTH"}, {WifiState::ROAMING_ASSOC, "ROAMING_ASSOC"}, {WifiState::LIGHT_SLEEP, "LIGHT_SLEEP"}, {WifiState::DEEP_SLEEP, "DEEP_SLEEP"} }; return stateMap.at(state); } public: WiFiStateMachine() { // 初始化定时器 esp_timer_create_args_t beacon_timer_args = { .callback = [](void* arg) { static_cast<WiFiStateMachine*>(arg)->checkBeacon(); }, .arg = this, .name = "beacon_timer" }; esp_timer_create(&beacon_timer_args, &beacon_timer); esp_timer_create_args_t sleep_timer_args = { .callback = [](void* arg) { static_cast<WiFiStateMachine*>(arg)->handleEvent(WifiEvent::SLEEP_ENTER); }, .arg = this, .name = "sleep_timer" }; esp_timer_create(&sleep_timer_args, &sleep_timer); // 注册WiFi事件处理 esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, [](void* arg, esp_event_base_t base, int32_t id, void* data) { auto self = static_cast<WiFiStateMachine*>(arg); switch(id) { case WIFI_EVENT_STA_CONNECTED: self->handleEvent(WifiEvent::CONNECTED); break; case WIFI_EVENT_STA_DISCONNECTED: self->handleEvent(WifiEvent::DISCONNECTED); break; case WIFI_EVENT_STA_AUTHMODE_CHANGE: // 认证处理 break; } }, this); } /** * 启动状态机 */ void start() { handleEvent(WifiEvent::SCAN_COMPLETE); } /** * 信标监测函数 */ void checkBeacon() { if (currentState == WifiState::CONNECTED) { // 检查信标是否丢失 if (/* 信标丢失检测逻辑 */) { handleEvent(WifiEvent::BEACON_LOST); } // 动态调整监测频率 adjustBeaconMonitoring(); // 检查漫游触发条件 wifi_ap_record_t ap_info; esp_wifi_sta_get_ap_info(&ap_info); if (ap_info.rssi < powerConfig.roam_threshold) { handleEvent(WifiEvent::ROAM_TRIGGER); } } } }; // 初始化WiFi(乐鑫专用API) extern "C" void app_main() { // WiFi初始化 wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); // 启动状态机 WiFiStateMachine stateMachine; stateMachine.start(); }不用针对乐鑫芯片写,直接用C++写代码,该有的功能要完整,注释要详细
最新发布
06-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值