Question

Somehow I need to make use of a class object inside of a pre-allocated memory. However,g++ doesn't like my code below. It's saying

invalid use of ‘CTest::CTest’ in line 26

How to change this to make it work?

#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;
}
Was it helpful?

Solution 2

Regarding the title of the question,

“Can I call the constructor and destructor of a class explicity?”

yes of course, e.g. you're calling the constructor very explicitly every time you create a temporary of the class (explicit destructor calls are more rare).

The standard confused this issue for a long time with its offhand comment “looks like an explicit constructor call”, but quite simply, explicit is explicit, and implicit is implicit, and call is call, and the standard does not redefine these terms. Regarding the term “call” as applied to constructors, the standard refers to source code level constructor “call”s e.g. in the definition of what a default constructor is. Anyway that’s a matter of terminology.

But the real question is different,

“I need to make use of a class object inside of a pre-allocated memory”

For this you can use an allocation function that simply returns the address that you pass it. And the standard library offers such an allocation function via the header <new>. To choose that “dummy” allocation function you can simply pass a pointer to your buffer as argument to it, so that it's selected by ordinary overload resolution.

To pass the pointer argument you can use placement new syntax, as follows:

#include <new>

// ...
 CTest* p_test = ::new (&ttt) CTest( "12345" );

where ttt is the buffer.

Note the global namespace qualification, which in general is needed in order to not pick up an allocation function defined by the class in question.

For this to work nicely –no crash, no fixup delay– the address you use must be of suitable alignment for the class. E.g., it may need to be a multiple of 4, or of 8, depending on the class. If the buffer comes from default new, then no problem, just use the start of the buffer, but I'm not so sure of malloc as it appears you’re using.

Do consult the documentation on that.

C++11 has some support for alignment, but your compiler may not necessarily offer that (yet). For platform-specific code you may not need to address this issue. However, if you want portable code you should make sure of correct alignment.

In practice one way to do it is to make your buffer 16 bytes larger than would strictly be necessary without the alignment requirement, and using a pointer to a place suitably offset from the start of the buffer.

OTHER TIPS

You cannot call the constructor directly. Instead, you have to use "placement new" for your object (What uses are there for "placement new"?). Which basically uses the memory you provide an calls the constructor. You can, however, call the destructor directly--simple call ~CTest() and don't call delete.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top