page 1 of 1
Comments: 2 | Views: 725
In a program I was thinking of writing for fun, I wanted to take a big chunk of memory from malloc() and then carve out various portions for different things so I only had to allocate memory once.

The problem with doing that is that according to one of Bjarne Stroustrup's books, the History and Evolution of C++, all C++ Objects have an extra pointer called the Virtual Function Table Pointer, which makes them distinctly different than C Structures. Furthermore, the creation of the Virtual Function Table to which this pointer points is handled by the compiler, so if I wanted to curve a chunk of memory into a bunch of C++ objects manually, I would have to allocate memory for this virtual function table, initializing its pointers and initializing the virtual function table pointer to point to this table.

It seems to me that where in an object the virtual function table pointer is (and the nature of its table when multiple inheritance is taken into consideration) is dependent on the compiler's implementation and that all of this should be handled by invisible code that the compiler inserts into the top of an object's constructor, which would have some relationship to the new operator that is normally used to create objects.

With this in mind, I did some research into the new operator and apparently, everything I outlined above is correct, but I have some questions about things I found when researching this topic.

My first question is regarding "new (p3.first) myclass[3];", which is from the following url:

http://www.cplusplus.com/reference/std/new/operator%20new%5B%5D.html

It is supposed to call the myclass constructor on 3 objects in an array pointed to by pointer p3.first, but it is the strangest/ugliest thing I have ever seen and it does not match the header definition provided on that page. Is there something in the C++ Grammar that make this sort of code a special case of a more general language feature or is this a special case (i.e. a hack) in the C++ grammar for seperating constructor calls from memory allocations?

The computer science classes I took to learn C/C++ tended to omit more exotic language features such as bit manipulation, variadic functions, etcetera, so I would not be surprised if "new (p3.first) myclass[3];" looks perfectly normal to more experienced programmers, but it appears very alien to me, which makes me think that I am missing something.

My second question is when you have a function:

someType someClass::someFunction () throw()
{

// code goes here

}

What does throw() mean? I used to know the answer to this, but I haven't written code in C++ for a year and I never wrote much involving exception handling. It seems to be functionally similar to the const keyword in that it labels a member function to be treated specially by the compiler, but that does not ring any bells in my mind that would answer this. My google searches have not been very helpful in searching for what throw() means.

Also, I am curious, does anyone know what the reasoning was that lead to the creation of get_temporary_buffer() and return_temporary_buffer()? I tried to answer that question myself by examining the code in <new>, but the code is so horribly obfuscated that the only possible reason get_temporary_buffer() and return_temporary_buffer() exist of which I can conceive is that they were convenient for someone at some early point in time because they could be used in place of C standard library functions for doing exactly what I want to do in my program and they were then incorporated into the standard because of that. I am kicking myself as I met Bjarne Stroustrup last year and I had been thinking about the very same topic a month before, but I did not do the research I did today to know about these two functions to able to ask him about them.

Edit: I just realized, how do you call the destructor of an object if you call its constructor in such a way?
1) I believe it comes from C++ operator overloading syntax which is a bit funky to say the least.

2) The throw(...) bit is an exception specifier. Specifically throw() means it won't throw an exception.

3) Probably seemed a good idea at the time. In some cases it might still be, I guess.

4) I think you just call delete[] on them as usual. I could be wrong though. The whole placement new thing is best avoided unless you have a very specific need for it.
Sven Groot
Sven Groot
My name has 9 letters. Coincidence? I think not...

The behaviour of operator new is a bit confusing. All that the function operator new (and operator new[]) does is allocate the memory. The actual operator (as oposed to the function) new (and new[]) first calls the function operator new to allocate the memory and then initializes the object. The syntax for the operator does not match the syntax of the function operator new (as you can see, the function operator new takes a size, while the actual operator new takes a type). The syntax for placement new is just weird.

Operator new is almost literally implemented as follows in many C++ implementations:

void* operator new (std::size_t size)<BR>{<BR>    void *result = malloc(size);<BR>    if( result == NULL )<BR>        throw std::bad_alloc();<BR>    else<BR>        return result;<BR>}


If you want to implement a custom memory manager for C++, all you really need to do is override the global operator new (similar to the code sample above, both new and new[] of course). You needn't bother with placement new, as Andy says, it's best avoided.

A word on exception specifiers. Unlike in Java, exception specifiers in C++ are basically useless. Their implementation is such that they actually mean "this function will only throw these exceptions. Well, maybe. Okay, actually we don't know". In Java, attempting to throw an exception that is not part of a function's specifier is a compile error. In C++, it will trigger no compile errors, but instead causes the global function "unexpected" to be called. You can hook up a custom handler for that, but there's only two things you can do: terminate the program or throw a new exception that the original function does allow. However, since inside the handler you don't know what function threw the exception, what exception was thrown, and what exceptions were allowed, there's nothing useful you can do. It's almost universally agreed on that exception specifiers in C++ are not really useful for anything.

In Visual C++, exception specifiers are even more useless. While VC can parse exception specifiers, it doesn't actually use them. The "unexpected" function is never called. VC only uses the presence of an empty exception specifier (throw()) as a hint to optimze away the exception handling and stack unwinding code (of course, should the function still throw an exception, your app will crash and there's no way to handle it anymore).

page 1 of 1
Comments: 2 | Views: 725
Microsoft Communities