TL;DR:创建一个指向std::string 的指针队列并在任一侧处理new/delete。确保生产者和消费者都在使用共享内存空间。
在像 FreeRTOS Queue 这样的“原始”内存 API 中使用 std::string 的问题实际上并不是对象大小的问题。事实上,std::string 对象的大小是固定的,与对象存储的字符数组的大小无关。不相信我?尝试在您自己的机器上编译和运行这个简单的程序:
#include <iostream>
int main(int argc, char **argv)
{
std::string str1 = "short";
std::string str2 = "very very very very very very long";
std::cout << "str1 length = " << sizeof(str1) << "\n";
std::cout << "str2 length = " << sizeof(str2) << "\n";
return 0;
}
你会得到这样的东西(实际大小会因你的平台而异):
str1 length = 24
str2 length = 24
请注意,如果您使用str1.size(),此结果会有所不同。
原因是像std::string 这样的标准库容器通常将它们的内容存储在malloc'ed 块中,因此std::string 对象本身只会存储一个指向包含字符串中字符数据的数组的指针。在这种情况下,sizeof() 从编译器的角度告诉您对象的大小,这将是指针和其他固定元数据(即结构的字段)的大小。 .size() 方法告诉您实现中的字符串大小,其中将包括对分配的字符数组的字符串长度计算。
您不能将std::string 对象复制到xQueueSend() 变体中的原因是生命周期管理问题。 FreeRTOS API 通过原始memcpy 执行*Send 和*Receive。标准库容器通常不是 POD 类型,这意味着它们必须通过专用的复制构造函数进行复制。如果您不这样做,您可能会使对象的某些内部状态无效,除非您真的知道自己在做什么。
因此,完成这项工作的最简单方法如下所示:
- 在
xQueueCreate() 上,将对象大小设置为sizeof(std::string *):
xQueue = xQueueCreate(NUM_OBJECTS, sizeof(std::string *));
- 在
xQueueSend() 上,通过运算符new 创建std::string,并将地址传递给该指针以进行复制。不要删除对象。
std::string *pStr = new std::string("hello world!");
xQueueSend(xQueue, &pStr, (TickType_t)0);
- 在
xQueueReceive() 上,复制出指针。用这个指针做你需要做的事情,然后delete它。
std::string *pStr = NULL;
xQueueReceive(xQueue, &pStr, (TickType_t)10);
// do stuff with pStr
delete pStr;