C++ ESP32上const char*的处理

C++ ESP32上const char*的处理,c++,esp32,C++,Esp32,我正在ESP32上进行一些Spotify API调用。对于C++,我是相当新的,而我似乎已经把它变成了我想要的,我想知道它是正确的方式还是最佳实践,还是我只是幸运而已。无论我读了多少书,关于字符和指针的整个事情对我来说仍然是相当混乱的 我正在调用SpotifyAPI,获取一个json响应,并使用ArduinoJson库解析它。库将所有键和值返回为const char* 我用来在屏幕上显示它的库也采用const char*。在将其转换为字符串之前,我让它工作,使用getTitle()函数返回字符串

我正在ESP32上进行一些Spotify API调用。对于C++,我是相当新的,而我似乎已经把它变成了我想要的,我想知道它是正确的方式还是最佳实践,还是我只是幸运而已。无论我读了多少书,关于字符和指针的整个事情对我来说仍然是相当混乱的

我正在调用SpotifyAPI,获取一个json响应,并使用ArduinoJson库解析它。库将所有键和值返回为
const char*
我用来在屏幕上显示它的库也采用
const char*
。在将其转换为字符串之前,我让它工作,使用getTitle()函数返回字符串并将其转换回屏幕显示。在我读到字符串效率低下且最好避免之后,我尝试减少转换步骤

void getTitle()
{
// I cut out the HTTP request and stuff
        DynamicJsonDocument doc(1024);
        DeserializationError error = deserializeJson(doc, http.getStream(), );
        JsonObject item = doc["item"];

        title = item["name"];  //This is a const char*

}
这样做可以吗?

这样不行。 当看到这样的事情时,你应该立即产生怀疑

这是因为在
getTitle
中,您向本地对象(
item
)请求一个指针,但当
item
对象不再存在时,您可以稍后使用该指针

这意味着一旦需要指针,它可能就没有意义了——它可能不再引用数据,而是引用其他任意字节(甚至导致崩溃)

这个问题与您使用的确切库无关,您通常可以通过搜索库文档中的“生存期”或“对象所有权”来找到相关的、更具体的信息

修理 使用数据时,请确保
(以及
动态SonDocument
,因为文档告诉您!)两者都仍然存在,例如:

void setTitle(const char*title)
{
u8g2.clearBuffer();
u8g2.setDrawColor(1);
u8g2.setFont(u8g2_font_6x12_tf);
u8g2.图纸(1,10,标题);
u8g2.sendBuffer();
}
void updateTitle()
{
动态文档文档(1024);
反序列化错误=deserializeJson(doc,http.getStream(),);
JsonObject item=doc[“item”];
设置标题(项目[“名称]);
}
另见:

编辑:如果要保持解析/显示更新解耦 您可以在需要解析数据时保持JSON文档“活动”:

/*“静态”可见性,使其他c/cpp文件(“翻译单元”)无法
*直接弄乱我们的JSON文档
*/
静态动态文档文档(1024);
静态常量字符*标题;
void parseJson()
{
[...]
//避免内存泄漏非常重要!!
doc.clear();
反序列化错误=deserializeJson(doc,http.getStream(),);
//TODO:健壮性/错误处理(例如,入站JSON缺少“项”)
标题=单据[“项目”][“名称”];
}
//在解析有效JSON之前调用时可能为nullptr
常量char*getTitle()
{
返回标题;
}
这不好。 当看到这样的事情时,你应该立即产生怀疑

这是因为在
getTitle
中,您向本地对象(
item
)请求一个指针,但当
item
对象不再存在时,您可以稍后使用该指针

这意味着一旦需要指针,它可能就没有意义了——它可能不再引用数据,而是引用其他任意字节(甚至导致崩溃)

这个问题与您使用的确切库无关,您通常可以通过搜索库文档中的“生存期”或“对象所有权”来找到相关的、更具体的信息

修理 使用数据时,请确保
(以及
动态SonDocument
,因为文档告诉您!)两者都仍然存在,例如:

void setTitle(const char*title)
{
u8g2.clearBuffer();
u8g2.setDrawColor(1);
u8g2.setFont(u8g2_font_6x12_tf);
u8g2.图纸(1,10,标题);
u8g2.sendBuffer();
}
void updateTitle()
{
动态文档文档(1024);
反序列化错误=deserializeJson(doc,http.getStream(),);
JsonObject item=doc[“item”];
设置标题(项目[“名称]);
}
另见:

编辑:如果要保持解析/显示更新解耦 您可以在需要解析数据时保持JSON文档“活动”:

/*“静态”可见性,使其他c/cpp文件(“翻译单元”)无法
*直接弄乱我们的JSON文档
*/
静态动态文档文档(1024);
静态常量字符*标题;
void parseJson()
{
[...]
//避免内存泄漏非常重要!!
doc.clear();
反序列化错误=deserializeJson(doc,http.getStream(),);
//TODO:健壮性/错误处理(例如,入站JSON缺少“项”)
标题=单据[“项目”][“名称”];
}
//在解析有效JSON之前调用时可能为nullptr
常量char*getTitle()
{
返回标题;
}

>如果使用C++,请忘记原始指针并使用STD::String。你会得到
title
作为一个悬而未决的指针。我建议你学习pointers@S.M.这是一个“小”平台(低速度和内存),询问者表示他们希望使代码更高效(在本例中,通过避免不必要的复制),我以前使用过字符串(String类应该是Arduino对std::String的改编)。现在,我试图避免这种情况。关于指针的内容/位置的更多信息?字符串非常有效。每个字符串对象上只保存4个字节,原始指针会出现很多问题。正如我所说的,指针悬空,必须将指向的C字符串复制到堆中。让字符串对象发挥最大作用。如果重新使用C++,忘记原始指针,使用STD::String。你得到的代码>标题<代码>是一个悬空指针。我建议你学习。pointers@S.M.这是一个“小”平台(低速度和内存),询问者表示他们希望提高代码的效率(在这种情况下,通过避免不必要的错误)
const char* title = nullptr;

void loop(void) {

    getTitle();

    u8g2.clearBuffer();
    u8g2.setDrawColor(1);
    u8g2.setFont(u8g2_font_6x12_tf);
    u8g2.drawStr(1, 10, title);
    u8g2.sendBuffer();
}