类属性尽量不要独立写 .cpp 文件
问题本质是"函数分离导致链接器过度保留 .o
文件"。最优解是把该函数实现挪进头文件并加 inline
。
正确写法:
cpp
// esp-ai.h
class ESP_AI {
public:
inline void onBegin(bool (*func)()) {
onBeginCb = func;
}
private:
bool (*onBeginCb)() = nullptr;
};
字符串形参尽量用 const String&
可以保证变量的安全性,也不会重复复制字符串。
正确写法:
arduino
void onSessionStatus(void (*func)(const String &status));
用法 | 内存消耗 | 推荐 | 说明 |
---|---|---|---|
String |
高 | ❌ | 动态内存,容易碎片 |
const char* |
低 | ✅ | 编译期常量,或者栈变量 |
snprintf + buf |
中 | ✅ | 控制好大小即可 |
任务用 xTaskCreateStatic,并且不要试图传入某个类的属性
正确写法:
scss
xTaskCreateStatic(light_task_static, "lights", 512, &light_ctx, 1, lightsTaskStack, &lightsTaskBuffer);
错误写法:
arduino
xTaskCreate(ClassName::play_audio_wrapper, "play_audio", 1024 * 2, this, 1, NULL);
头文件中如果不直接使用第三方类时使用前向声明
🧠 什么时候可以使用 forward declare?
使用场景 | 是否可以 forward declare |
---|---|
只声明指针或引用 Foo* |
✅ 可以 |
不需要访问 Foo 的成员变量 |
✅ 可以 |
需要 new Foo() 或 .bar() |
❌ 不可以,需要完整类定义 |
定义成员变量 Foo foo; |
❌ 不可以,必须 include |
arduino
#pragma once
// 不包含大库,使用前向声明代替 #include
class DriverPins;
class AudioBoard;
class I2SCodecStream;
template <typename T> class QueueStream; // ✅ 模板类的前向声明需写成这样
class EncodedAudioStream;
class TwoWire;
// 结构体定义:保留字段但注释掉以测试内存差异
struct SpeakerI2SContent {
DriverPins *esp_ai_audio_pins;
AudioBoard *esp_ai_audio_board;
I2SCodecStream *esp_ai_spk_i2s;
QueueStream<uint8_t> *esp_ai_spk_queue;
EncodedAudioStream *esp_ai_dec;
TwoWire *esp_ai_audio_wire;
};
// 函数声明
void speaker_i2s_setup(SpeakerI2SContent *content);