不知何故,我需要在预先分配的内存中使用一个类对象。但是,g ++不喜欢我下面的代码。它在说
invalid use of ‘CTest::CTest’ in line 26
如何更改此功能以使其正常工作?
#include <stdio.h>
#include <stdlib.h>
#include <string>
class CTest
{
public:
CTest(const char* str)
{
printf("constructor\n");
m_str = str;
}
virtual ~CTest()
{
printf("destructor\n");
}
void output()
{
printf("output:%s\n", m_str.c_str());
}
protected:
std::string m_str;
};
struct TTT
{
char test_ptr[sizeof(CTest)];
};
int main(int argc, char* argv[])
{
struct TTT* ttt = (struct TTT*)malloc(sizeof(struct TTT));
CTest* test = (CTest*)(ttt->test_ptr);
test->CTest("123456");
test->output();
test->~CTest();
return 0;
}
答案 0 :(得分:2)
您无法直接调用构造函数。相反,你必须使用&#34; placement new&#34;为你的对象(What uses are there for "placement new"?)。其中基本上使用你提供的内存来调用构造函数。但是,您可以直接调用析构函数 - 简单调用~CTest()并且不要调用delete。
答案 1 :(得分:1)
关于问题的标题,
“我可以调用类显式的构造函数和析构函数吗?”
当然是的,例如每次创建一个临时类时,你都会非常明确地调用构造函数(显式的析构函数调用更为罕见)。
标准混淆了这个问题很长一段时间它的随意评论“看起来像一个显式的构造函数调用”,但很简单,显式是显式的,隐式是隐式的,调用是调用,标准不重新定义这些条款。关于应用于构造函数的术语“调用”,该标准指的是源代码级构造函数“调用”,例如,在默认构造函数的定义中。无论如何,这是一个术语问题。
但真正的问题是不同的,
“我需要在预先分配的内存中使用类对象”
为此,您可以使用仅返回传递地址的分配函数。标准库通过标题<new>
提供这样的分配功能。要选择“虚拟”分配函数,您只需将指针作为参数传递给缓冲区,以便通过普通的重载决策选择它。
要传递指针参数,您可以使用展示位置新语法,如下所示:
#include <new>
// ...
CTest* p_test = ::new (&ttt) CTest( "12345" );
其中ttt
是缓冲区。
请注意全局命名空间限定,通常需要这样才能获取由相关类定义的分配函数。
为了使其正常工作 - 没有崩溃,没有修复延迟 - 您使用的地址必须适合该类的对齐。例如,它可能需要是4或8的倍数,具体取决于班级。如果缓冲区来自默认new
,那么没问题,只需使用缓冲区的开头,但我不确定malloc
是否正如您正在使用的那样。
请参阅相关文档。
C ++ 11对对齐有一些支持,但你的编译器可能不一定提供(但)。对于特定于平台的代码,您可能不需要解决此问题。但是,如果您需要可移植代码,则应确保正确对齐。
实际上,一种方法是使缓冲区比没有对齐要求时严格需要的16个字节大,并使用一个指向缓冲区起始位置的指针。