Overloading global new and delete safely
While reading Bruce Eckel i came across the following example:
#include <cstdio>
#include <cstdlib>
using namespace std;
void* operator new(size_t sz)
{
printf("operator new: %d Bytes\n", sz);
void* m = malloc(sz);
if(!m) puts("out of memory");
return m;
}
void operator delete(void* m)
{
puts("operator delete");
free(m);
}
class S {
int i[100];
public:
S() { puts("S::S()"); }
~S() { puts("S::~S()"); }
};
int main() {
puts("creating & destroying an int");
int* p = new int(47);
delete p;
puts("creating & destroying an s");
S* s = new S;
delete s;
puts("creating & destroying S[3]");
S* sa = new S[3];
delete []sa;
}
I am having doubt with following statement:
Notice that
However, when i am running the program after replacing put withprintf( )
andputs( )
are used rather than iostreams. This is because when aniostream
object is created (like the globalcin
,cout
, andcerr
), it callsoperator new
to allocate memory. Withprintf( )
, you don't get into a deadlock because it doesn't callnew
to initialize itself.cout
i am getting no such deadlock. Can anyone explain that?operator new
returns a void pointer, but finally we are getting pointer to a dynamically allocated object. So is it a constructor that returns a pointer to the object (this, though the constructor开发者_开发技巧 doesn't have a return type) or its the compiler that does i internally?
1) The C++ standard contains a lot of "mays" which are not usually used. This is one of them. The operator<< function may use dynamic memory, but it does not have to. Often this is not the case.
So that your example works does not mean it is correct. It just means it works with the implementation you are using. On other implementations it could break.
The "mays" defined by the standard can also go in another direction. For example any STL-Header may include any other standard header, but is not required to do so. This is often the case with the iostream header and the istream and ostream headers. Almost any implementation includes ostream and istream when iostream is used, but technically they don't have to. This means when you use ostream and just include iostream you program might work, but actually it is not correct as far as the standard is concerned.
For both c and c++ it is rather important to know what may silently break, but this is often not very easy.
Use of
printf()
to avoid a recursive call intooperator new()
is a safety measure - just to be sure it works. How do you know use ofiostream
never ever causes a call tooperator new()
function?You're confusing new expression (a language construct) with
operator new()
function. new expression indeed returns a typed pointer, but the a call tooperator new()
function is done "under the hood" andoperator new()
function returnsvoid*
. The compiler generates all necessary code for that.
精彩评论