C++ 初始化未初始化的无主内存中的std::string

C++ 初始化未初始化的无主内存中的std::string,c++,c++11,C++,C++11,我正在使用一个C库(libwebsockets),它允许为每个客户机提供一些用户数据。库拥有此内存,将其作为void*传递,然后我的代码将其重新解释为我的用户数据类型 我试图向这个类添加一个std::string字段,现在看到了segfaults。在此类上调用函数会导致错误,这是公平的,因为它可能由未初始化的内存支持 如何初始化该内存>我已尝试分配(赋值运算符SEGFULTS)并调用各种函数,如清除。我猜这有一个C++机制。< /P> 此外,当不再需要字符串时,如何调用析构函数?您可以使用pla

我正在使用一个C库(libwebsockets),它允许为每个客户机提供一些用户数据。库拥有此内存,将其作为
void*
传递,然后我的代码
将其重新解释为我的用户数据类型

我试图向这个类添加一个
std::string
字段,现在看到了segfaults。在此类上调用函数会导致错误,这是公平的,因为它可能由未初始化的内存支持

如何初始化该内存>我已尝试分配(赋值运算符SEGFULTS)并调用各种函数,如
清除
。我猜这有一个C++机制。< /P>
此外,当不再需要字符串时,如何调用析构函数?

您可以使用placement new在提供的内存中创建对象:

std::string * s = new(memory) std::string;
并在重用或释放内存之前调用析构函数销毁它:

s->std::string::~string();

如果你觉得有点过分,那么使用std::string
会将其减少为
s->~string()

假设您有如下类型:

class MyType
{
    std::string foo;
    std::string bar;
};
假设
void*
指向至少
sizeof(MyType)
字节的未初始化分配,则可以使用placement new语法构造它(以及所有包含的对象):

void init_callback(void * ptr) {
    new (ptr) MyType();
}
类似地,您可以通过直接调用析构函数来销毁您的类型(它将销毁所有包含的对象)

void destroy_callback(void * ptr) {
    MyType * mine = reinterpret_cast<MyType *>(ptr);
    mine->~MyType();
}
void destroy\u回调(void*ptr){
MyType*mine=重新解释铸件(ptr);
我的->~MyType();
}

通常不直接调用析构函数,但必须这样做,因为无法安全地
删除
指针。“每个
new
都应该有一个
delete
”规则在这种情况下有一个类似的规则:“每个新的位置都应该有一个对析构函数的显式调用。”

如果
void*
指向的内存没有被分配为您将其强制转换到的类型的对象,那么内存当然不会被初始化。有点不清楚是谁在进行堆分配,以及他们是如何进行的;这是这个问题的一个重要部分。@cdhowie,libwebsockets为每个客户机分配内存。我只告诉它每个客户端需要多少字节,当客户端连接时,它会给我一个
void*
,然后在每个回调中。在一些API中,我看到了这被称为闭包。如果你想初始化分配的内存,尝试<代码>放置新的< /Cord> @ DrWoNokes是的,你可以直接调用析构函数:<代码> PTR> ~NAMEOFFIDENTY()/WORD >哇,C++标签上填充了不提供任何建设性理由的下沉巨魔。我真的不在乎否决票,但与其他语言相比,它创建了一个更不具包容性的子社区。我只是想报告一下,并说这种方法产生了干净、可理解的代码,甚至可以工作:)再次感谢。为什么要在
new
之前投票?@Yakk确实没有必要。我在写它的时候想到了析构函数的例子,但忘了回去编辑它。至少它不会造成伤害,也不会对代码生成器造成任何更改,因为它可以全部优化。@NeilKirk它不需要
decltype
。。就这样。我补充了这一点,以说明如何使用
unique\u ptr
实现这一点。