我可以显式调用类的构造函数和析构函数吗?

时间:2014-03-11 18:10:01

标签: c++ constructor g++ destructor

不知何故,我需要在预先分配的内存中使用一个类对象。但是,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;
}

2 个答案:

答案 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个字节大,并使用一个指向缓冲区起始位置的指针。

相关问题