Can you call the destructor without calling the constructor? - c++

I've been trying not to initialize memory when I don't need to, and am using malloc arrays to do so:
This is what I've run:
#include <iostream>
struct test
{
int num = 3;
test() { std::cout << "Init\n"; }
~test() { std::cout << "Destroyed: " << num << "\n"; }
};
int main()
{
test* array = (test*)malloc(3 * sizeof(test));
for (int i = 0; i < 3; i += 1)
{
std::cout << array[i].num << "\n";
array[i].num = i;
//new(array + i) i; placement new is not being used
std::cout << array[i].num << "\n";
}
for (int i = 0; i < 3; i += 1)
{
(array + i)->~test();
}
free(array);
return 0;
}
Which outputs:
0 ->- 0
0 ->- 1
0 ->- 2
Destroyed: 0
Destroyed: 1
Destroyed: 2
Despite not having constructed the array indices. Is this "healthy"? That is to say, can I simply treat the destructor as "just a function"?
(besides the fact that the destructor has implicit knowledge of where the data members are located relative to the pointer I specified)
Just to specify: I'm not looking for warnings on the proper usage of c++. I would simply like to know if there's things I should be wary of when using this no-constructor method.
(footnote: the reason I don't wanna use constructors is because many times, memory simply does not need to be initialized and doing so is slow)

No, this is undefined behaviour. An object's lifetime starts after the call to a constructor is completed, hence if a constructor is never called, the object technically never exists.
This likely "seems" to behave correctly in your example because your struct is trivial (int::~int is a no-op).
You are also leaking memory (destructors destroy the given object, but the original memory allocated via malloc still needs to be freed).
Edit: You might want to look at this question as well, as this is an extremely similar situation, simply using stack allocation instead of malloc. This gives some of the actual quotes from the standard around object lifetime and construction.
I'll add this as well: in the case where you don't use placement new and it clearly is required (e.g. struct contains some container class or a vtable, etc.) you are going to run into real trouble. In this case, omitting the placement-new call is almost certainly going to gain you 0 performance benefit for very fragile code - either way, it's just not a good idea.

Yes, the destructor is nothing more than a function. You can call it at any time. However, calling it without a matching constructor is a bad idea.
So the rule is: If you did not initialize memory as a specific type, you may not interpret and use that memory as an object of that type; otherwise it is undefined behavior. (with char and unsigned char as exceptions).
Let us do a line by line analysis of your code.
test* array = (test*)malloc(3 * sizeof(test));
This line initializes a pointer scalar array using a memory address provided by the system. Note that the memory is not initialized for any kind of type. This means you should not treat these memory as any object (even as scalars like int, let aside your test class type).
Later, you wrote:
std::cout << array[i].num << "\n";
This uses the memory as test type, which violates the rule stated above, leading to undefined behavior.
And later:
(array + i)->~test();
You used the memory a test type again! Calling destructor also uses the object ! This is also UB.
In your case you are lucky that nothing harmful happens and you get something reasonable. However UBs are solely dependent on your compiler's implementation. It can even decide to format your disk and that's still standard-conforming.

That is to say, can I simply treat the destructor as "just a function"?
No. While it is like other functions in many ways, there are some special features of the destructor. These boil down to a pattern similar to manual memory management. Just as memory allocation and deallocation need to come in pairs, so do construction and destruction. If you skip one, skip the other. If you call one, call the other. If you insist upon manual memory management, the tools for construction and destruction are placement new and explicitly calling the destructor. (Code that uses new and delete combine allocation and construction into one step, while destruction and deallocation are combined into the other.)
Do not skip the constructor for an object that will be used. This is undefined behavior. Furthermore, the less trivial the constructor, the more likely that something will go wildly wrong if you skip it. That is, as you save more, you break more. Skipping the constructor for a used object is not a way to be more efficient — it is a way to write broken code. Inefficient, correct code trumps efficient code that does not work.
One bit of discouragement: this sort of low-level management can become a big investment of time. Only go this route if there is a realistic chance of a performance payback. Do not complicate your code with optimizations simply for the sake of optimizing. Also consider simpler alternatives that might get similar results with less code overhead. Perhaps a constructor that performs no initializations other than somehow flagging the object as not initialized? (Details and feasibility depend on the class involved, hence extend outside the scope of this question.)
One bit of encouragement: If you think about the standard library, you should realize that your goal is achievable. I would present vector::reserve as an example of something that can allocate memory without initializing it.

You currently have UB as you access field from non-existing object.
You might let field uninitialized by doing a constructor noop. compiler might then easily doing no initialization, for example:
struct test
{
int num; // no = 3
test() { std::cout << "Init\n"; } // num not initalized
~test() { std::cout << "Destroyed: " << num << "\n"; }
};
Demo
For readability, you should probably wrap it in dedicated class, something like:
struct uninitialized_tag {};
struct uninitializable_int
{
uninitializable_int(uninitialized_tag) {} // No initalization
uninitializable_int(int num) : num(num) {}
int num;
};
Demo

Related

Easier way to have shared_ptr own an existing pointer

Many programmers advocate the use of make_shared because it reduces typing and reduces programming errors. However there are some cases where using the constructors of shared_ptr is unavoidable. One of these cases is when you have an existing pointer that you want shared_ptr to own, since shared_ptr<Foo>(&existing_ptr) is bad code. Instead, you have to use the unwieldy shared_ptr<Foo>(shared_ptr<Foo>(), p). Not only are you repeating yourself, but you have to create a temporary object.
int main()
{
using namespace std;
Foo foo;
foo.n = 1;
{
auto ptr = make_shared<Foo>(move(foo));
ptr->n = 42;
cout << ptr->n << " " << foo.n << '\n';
}
{
auto p = &foo;
auto ptr = shared_ptr<Foo>(shared_ptr<Foo>(), p);
ptr->n = 42;
cout << ptr->n << " " << foo.n << '\n';
}
return 0;
}
Foo::Foo()
Foo::Foo(Foo &&)
42 1
Foo::~Foo()
42 42
Foo::~Foo()
What's a less verbose way to have shared_ptr own an existing pointer?
The intended use of that constructor is to allow shared pointers to sub objects of shared pointers.
Your use is not the intended use, and is quite dangerous, as you have implicitly created a guarantee that the data you are passing to the shared pointer will last as long as the shared pointer or its copies does, and then failing to enforce that guarantee in any meaningful sense.
If you pass a shared pointer to a function, it has every right to cache a copy if it and use it 15 minutes later. And if you aren't passing a shared pointer to a function, you don't need one.
In general, a function should only require a shared pointer if it intends to extend the lifetime of its argument in a difficult to predict way. So if you have a function that takes a shared pointer and never extends its lifetime (or the lifetime of a pointer to it), it should not be taking a shared pointer. The problem is in the function you are calling, not with how you have to jump through hoops to call it.
Only when you both have a function that is broken, and are unable to fix it and making a copy of Foo on the free store is overly expensive, is your technique worth trying. And that should be extreme corner cases anyhow.
IMO what you're doing there shouldn't be easy because it's very dangerous, and only necessary under highly specialized circumstances where typing a class name twice should be the least of your worries.
But here is a slightly more succinct way to achieve the same thing by using a dummy deleter:
auto ptr = std::shared_ptr<Foo>(&foo, [](void*){});
Also, in your approach it isn't really correct to say that ptr owns foo; rather it owns the null object in the empty std::shared_ptr<Foo> and points to foo (see this answer for a longer discussion). In my code above it does "own" foo in some technical sense (or at least it thinks it does); it's just been prevented from doing anything to it when its reference count reaches zero.

Is it a better way to use an Init() for memory allocation than Constructor?

Suppose I have things like:
class obj001
{
public:
obj001() {
std::cout << "ctor == obj001" << std::endl;
}
~obj001() {
std::cout << "dtor == obj001" << std::endl;
}
};
class obj002
{
public:
obj002() {
std::cout << "ctor == obj002" << std::endl;
}
~obj002() {
std::cout << "dtor == obj002" << std::endl;
}
};
class packet001
{
public:
packet001(): p01(NULL), p02(NULL) {
/*p01 = new obj001;
p02 = new obj002;
throw "hahaha";*/
std::cout << "CTOR == PACKET01" << std::endl;
}
~packet001() {
delete p01;
delete p02;
std::cout << "DTOR == PACKET01" << std::endl;
}
void init() {
p01 = new obj001;
p02 = new obj002;
throw "hahaha";
}
obj001* p01;
obj002* p02;
};
And if I do:
try
{
packet001 superpack;
superpack.init();
}
catch(char* type)
{
}
Then the init() failed, and the Dtor of superpack will be called.
But if I put memory allocation inside the Ctor of superpack,
(And do not execute init(), of course)
then after the Ctor failed, the Dtor will not be called, so p01 and p02 are leaked.
So, it it better to use things like init()?
Thanks!
Using two phase construction, ordinary construction followed by an outside call to an initfunction, means that after construction you don't know yet whether you have a valid object at hand. And that means that in any function that gets such an object as argument, you don't know whether the object is valid. This means a lot of extra checking and uncertainty which in turn means bugs and added work, so, a constructor should instead establish a fully functional, valid object.
The set of assumptions that go into the notion of "functional, valid" is called the class invariant.
So in other words, more academic phrasing, the job of a constructor is to establish the class invariant, so that it’s known to hold after construction.
Then keeping the object valid in every externally available operation, means that it will continue to be guaranteed valid. Thus no further validity checking is required. This scheme isn’t entirely 100% applicable to all objects (a counter-example is an object representing a file, where any operation might cause the object to become effectively invalid), but mostly it’s a good idea and works well, and where it doesn't work directly, it works for the parts.
So in your constructor you should ensure cleanup by one of the following means:
Use standard library containers (or 3rd party ones) instead of dealing directly with raw arrays and dynamic allocation.
Or use sub-objects that each manage just one resource. A sub-object can be a data member or a base class. If a data member, it can be smart pointer.
Or in the worst case, use try-catch for direct cleanup.
It’s also technically possible to use the C idea of checking return values to invoke direct cleanup as necessary. But the list above is in order of decreasing ease and safety. The C style coding is somewhere beyond the bottom of that list.
The C++ language creator, Bjarne Stroustrup, has written a little about this very subject, in his appendix Appendix E: Standard-Library Exception Safety appendix to the 3rd edition of The C++ Programming Language. Just download the PDF, and in your PDF reader search for “init(”. You should land directly a bit into section §E3.5, about Constructors and Invariants; do read on through at least section §E.3.5.1 about Using init() Functions.
As Bjarne lists there, …
[…] having a separate init() function is an opportunity to
[1] forget to call init() (§10.2.3),
[2] forget to test on the success of init(),
[3] call init() more than once,
[4] forget that init()might throw an exception, and
[5] use the object before calling init().
Bjarne’s discussion is, I think, great for a beginner, as is the whole book.
However, be aware that a common reason for two-phase construction, namely to support derived class specific initialization, is simply not mentioned at all, not part of Bjarne’s picture here. This is the reason for two-phase initialization in many GUI frameworks. Some C++ GUI frameworks with OK single phase initialization do exist, however, proving that mostly it was all an educational issue – that those early C++ programmers simply did not know about, or could not assume that their library users would understand, C++ RAII.
The best thing is to avoid these kinds of allocations altogether. You can put instances directly within a class for many things. If you really need a pointer, you can use unique_ptr and shared_ptr for automatic memory management.
In your example, this would be fine:
struct packet001
{
obj001 p01;
obj002 p02;
};
If you need them to be pointers:
struct packet001
{
packet001()
: p01(new obj001),
p02(new obj002)
{
}
std::unique_ptr<obj001> p01;
std::unique_ptr<obj002> p02;
};
The memory will automatically be freed in the destructor, and deallocations will happen properly if an exception occurs during construction.
Shouldn't you catch all exceptions in Ctor and clean up properly if exceptions arrive inside Ctor?
I have used two phase construction, or various other means pointed out for in constructor cleanup, in instances where the constructor is likely to fail many a times AND where I want the program to continue to run even after that failure; e.g. trying to construct an object that reads a file, where the file name was provided by the user. There the constructor is likely to fail many a times, e.g. on bad user input.
But bad_alloc - that should be rare for a well designed program. And what exactly are you going to do if the memory allocation fails? Your C++ program is most likely doomed at that point of time. Why worry about a memory leak at that point of time? Now you can point out some counter examples where programs can continue to run even after encountering a bad alloc, OR programs which employ fancy techniques to avoid bad_allocs, but is your program one of those?

Order of destruction for Array of Objects

class MyClass
{
};
void foo
{
MyClass arr[10];
}
I want to know the order of destruction of array objects when function returns.
I read it More Effective C++ about it and it says that destructor are invoked in reverse
order to that of constructor order as follows:
for(int i = 9 ; i >= 0 ;i--)
{
arr[i].MyClass::~MyClass();
}
Can anybody tell me the reason for it ?
That's continuation of reverse order of destructor invokation filosophy of C++. When stack-allocated objects are destroyed it is done in reverse order to facilitate RAII. Although that is not really necessary for array elements (they are all constructed with the default constructors and any order of construction/destruction would do) the same is done with them just for consistency.
The information you're referring to in More Effective C++ applies to objects that contain a couple of other object, as in this case:
class Foo {
private:
Bar bar_1;
Bar bar_2;
public:
Foo() : bar_1(), bar_2() {}
};
In the above example, you'll have bar_1 constructed first, followed by bar_2. When an object of class Foo then gets destroyed, bar_2 gets destroyed first, then bar_1. That is what Scott Meyers is referring to.
From the point of view of the class, an array of bars would be another object that the compiler needs to destroy, so the order of destruction affects when the array gets destructed in the context of the other objects in the class.
As to which order the elements of an array get destroyed, I wouldn't be too surprised if that is implementation dependent. You'll also have optimisation playing a role here (for example, a POD array can be destroyed just by freeing its memory, as can be an object that is solely composed of PODs). All of the above can affect the order in which the elements of an array will be destroyed.
I'd be interested to see why you do need to know the order in which the array elements are destroyed (apart from technical curiosity, which would be a valid reason IMHO). If it is because there are dependencies between the elements of the array, I think the data structure might need reviewing.
Any order would do, really. The two obvious choices are of course in order or in reverse order. However, in this case none of the compiler makers thought it would be worthwhile to leave this implementation-dependent. Hence, the choice was made to mandate the reverse order (as sharptooth stated, extending the usual LIFO behavior)
You don't cite which page in Meyer's book you are referring to, but I agree with Timo Geusch that the explanation sounds like it is referring to the that constructors and destructors are invoked according to the inheritance.
For an array of object instances, the order that objects are destroyed is the inverse of the order of construction. This is easy to verify, as the following code shows. A class variable keeps track of the total number of instances created, and a data member for each object keeps track of its own number. The constructor and destructor print a message, so when run we can see exactly what happens and when.
The test code prints out the count of objects from 0 to 9 when constructing, then from 9 down to 0 when destructing the instances. (This was tested with g++-4.2 on Mac OS X.)
#include <iostream>
class MyClass
{
public:
MyClass()
{
mCounter = kInstanceCount++;
std::cout << "+++ MyClass() " << mCounter << std::endl;
}
~MyClass()
{
std::cout << "--- MyClass() " << mCounter << std::endl;
}
private:
unsigned mCounter;
static unsigned kInstanceCount;
};
unsigned MyClass::kInstanceCount = 0;
int main()
{
MyClass arr[10];
return 0;
}
You would need to check the C++ Standard, as I'm not 100% sure that this is not an implementation detail (as is often the case), in which case you don't want to rely on this behaviour.
Note also that it is not so common to create a stack-based array of actual object instances. You are more likely to be using std::vector, or maybe using smart pointers to heap-allocated objects.
Perhaps the order in which the objects that make up the array are placed on the stack. Anyway, except curiosity, I can think of no reason to worry about the destruction order.

Returning Large Objects in Functions

Compare the following two pieces of code, the first using a reference to a large object, and the second has the large object as the return value. The emphasis on a "large object" refers to the fact that repeated copies of the object, unnecessarily, is wasted cycles.
Using a reference to a large object:
void getObjData( LargeObj& a )
{
a.reset() ;
a.fillWithData() ;
}
int main()
{
LargeObj a ;
getObjData( a ) ;
}
Using the large object as a return value:
LargeObj getObjData()
{
LargeObj a ;
a.fillWithData() ;
return a ;
}
int main()
{
LargeObj a = getObjData() ;
}
The first snippet of code does not require copying the large object.
In the second snippet, the object is created inside the function, and so in general, a copy is needed when returning the object. In this case, however, in main() the object is being declared. Will the compiler first create a default-constructed object, then copy the object returned by getObjData(), or will it be as efficient as the first snippet?
I think the second snippet is easier to read but I am afraid it is less efficient.
Edit: Typically, I am thinking of cases LargeObj to be generic container classes that, for the sake of argument, contains thousands of objects inside of them. For example,
typedef std::vector<HugeObj> LargeObj ;
so directly modifying/adding methods to LargeObj isn't a directly accessible solution.
The second approach is more idiomatic, and expressive. It is clear when reading the code that the function has no preconditions on the argument (it does not have an argument) and that it will actually create an object inside. The first approach is not so clear for the casual reader. The call implies that the object will be changed (pass by reference) but it is not so clear if there are any preconditions on the passed object.
About the copies. The code you posted is not using the assignment operator, but rather copy construction. The C++ defines the return value optimization that is implemented in all major compilers. If you are not sure you can run the following snippet in your compiler:
#include <iostream>
class X
{
public:
X() { std::cout << "X::X()" << std::endl; }
X( X const & ) { std::cout << "X::X( X const & )" << std::endl; }
X& operator=( X const & ) { std::cout << "X::operator=(X const &)" << std::endl; }
};
X f() {
X tmp;
return tmp;
}
int main() {
X x = f();
}
With g++ you will get a single line X::X(). The compiler reserves the space in the stack for the x object, then calls the function that constructs the tmp over x (in fact tmp is x. The operations inside f() are applied directly on x, being equivalent to your first code snippet (pass by reference).
If you were not using the copy constructor (had you written: X x; x = f();) then it would create both x and tmp and apply the assignment operator, yielding a three line output: X::X() / X::X() / X::operator=. So it could be a little less efficient in cases.
Use the second approach. It may seem that to be less efficient, but the C++ standard allows the copies to be evaded. This optimization is called Named Return Value Optimization and is implemented in most current compilers.
Yes in the second case it will make a copy of the object, possibly twice - once to return the value from the function, and again to assign it to the local copy in main. Some compilers will optimize out the second copy, but in general you can assume at least one copy will happen.
However, you could still use the second approach for clarity even if the data in the object is large without sacrificing performance with the proper use of smart pointers. Check out the suite of smart pointer classes in boost. This way the internal data is only allocated once and never copied, even when the outer object is.
The way to avoid any copying is to provide a special constructor. If you
can re-write your code so it looks like:
LargeObj getObjData()
{
return LargeObj( fillsomehow() );
}
If fillsomehow() returns the data (perhaps a "big string" then have a constructor that takes a "big string". If you have such a constructor, then the compiler will very likelt construct a single object and not make any copies at all to perform the return. Of course, whether this is userful in real life depends on your particular problem.
A somewhat idiomatic solution would be:
std::auto_ptr<LargeObj> getObjData()
{
std::auto_ptr<LargeObj> a(new LargeObj);
a->fillWithData();
return a;
}
int main()
{
std::auto_ptr<LargeObj> a(getObjData());
}
Alternatively, you can avoid this issue all together by letting the object get its own data, i. e. by making getObjData() a member function of LargeObj. Depending on what you are actually doing, this may be a good way to go.
Depending on how large the object really is and how often the operation happens, don't get too bogged down in efficiency when it will have no discernible effect either way. Optimization at the expense of clean, readable code should only happen when it is determined to be necessary.
The chances are that some cycles will be wasted when you return by copy. Whether it's worth worrying about depends on how large the object really is, and how often you invoke this code.
But I'd like to point out that if LargeObj is a large and non-trivial class, then in any case its empty constructor should be initializing it to a known state:
LargeObj::LargeObj() :
m_member1(),
m_member2(),
...
{}
That wastes a few cycles too. Re-writing the code as
LargeObj::LargeObj()
{
// (The body of fillWithData should ideally be re-written into
// the initializer list...)
fillWithData() ;
}
int main()
{
LargeObj a ;
}
would probably be a win-win for you: you'd have the LargeObj instances getting initialized into known and useful states, and you'd have fewer wasted cycles.
If you don't always want to use fillWithData() in the constructor, you could pass a flag into the constructor as an argument.
UPDATE (from your edit & comment) : Semantically, if it's worthwhile to create a typedef for LargeObj -- i.e., to give it a name, rather than referencing it simply as typedef std::vector<HugeObj> -- then you're already on the road to giving it its own behavioral semantics. You could, for example, define it as
class LargeObj : public std::vector<HugeObj> {
// constructor that fills the object with data
LargeObj() ;
// ... other standard methods ...
};
Only you can determine if this is appropriate for your app. My point is that even though LargeObj is "mostly" a container, you can still give it class behavior if doing so works for your application.
Your first snippet is especially useful when you do things like have getObjData() implemented in one DLL, call it from another DLL, and the two DLLs are implemented in different languages or different versions of the compiler for the same language. The reason is because when they are compiled in different compilers they often use different heaps. You must allocate and deallocate memory from within the same heap, else you will corrupt memory. </windows>
But if you don't do something like that, I would normally simply return a pointer (or smart pointer) to memory your function allocates:
LargeObj* getObjData()
{
LargeObj* ret = new LargeObj;
ret->fillWithData() ;
return ret;
}
...unless I have a specific reason not to.

method running on an object BEFORE the object has been initialised?

#include <iostream>
using namespace std;
class Foo
{
public:
Foo(): initialised(0)
{
cout << "Foo() gets called AFTER test() ?!" << endl;
};
Foo test()
{
cout << "initialised= " << initialised << " ?! - ";
cout << "but I expect it to be 0 from the 'initialised(0)' initialiser on Foo()" << endl;
cout << "this method test() is clearly working on an uninitialised object ?!" << endl;
return Foo();
}
~Foo()
{};
private:
int initialised;
};
int main()
{
//SURE this is bad coding but it compiles and runs
//I want my class to DETECT and THROW an error to prevent this type of coding
//in other words how to catch it at run time and throw "not initialised" or something
Foo foo=foo.test();
}
Yes, it is calling the function on a yet not constructed object, which is undefined behavior. You can't detect it reliable. I would argue you also should not try to detect it. It's nothing which would happen likely by accident, compared to for example calling a function on an already deleted object. Trying to catch every and all possible mistakes is just about impossible. The name declared is visible already in its initializer, for other useful purposes. Consider this:
Type *t = (Type*)malloc(sizeof(*t));
Which is a common idiom in C programming, and which still works in C++.
Personally, i like this story by Herb Sutter about null references (which are likewise invalid). The gist is, don't try to protect from cases that the language clearly forbids and in particular are in their general case impossible to diagnose reliably. You will get a false security over time, which becomes quite dangerous. Instead, train your understanding of the language and design interfaces in a way (avoid raw pointers, ...) that reduces the chance of doing mistakes.
In C++ and likewise in C, many cases are not explicitly forbidden, but rather are left undefined. Partially because some things are rather difficult to diagnose efficiently and partially because undefined behavior lets the implementation design alternative behavior for it instead of completely ignoring it - which is used often by existing compilers.
In the above case for example, any implementation is free to throw an exception. There are other situations that are likewise undefined behavior which are much harder to diagnose efficiently for the implementation: Having an object in a different translation unit accessed before it was constructed is such an example - which is known as the static initialization order fiasco.
The constructor is the method you want (not running before initialization but rather on initialization, but that should be OK). The reason it doesn't work in your case is that you have undefined behavior here.
Particularly, you use the not-yet-existent foo object to initialize itself (eg. the foo in foo.Test() doesn't exist yet). You can solve it by creating an object explicitly:
Foo foo=Foo().test()
You cannot check for it in the program, but maybe valgrind could find this type of bug (as any other uninitialized memory access).
You can't prevent people from coding poorly, really. It works just like it "should":
Allocate memory for Foo (which is the value of the "this" pointer)
Going to Foo::test by doing: Foo::test(this), in which,
It gets the value by this->initialised, which is random junk, then it
Calls Foo's default constructor (because of return Foo();), then
Call Foo's copy constructor, to copy the right-handed Foo().
Just like it should. You can't prevent people from not knowing the right way to use C++.
The best you could do is have a magic number:
class A
{
public:
A(void) :
_magicFlag(1337)
{
}
void some_method(void)
{
assert (_magicFlag == 1337); /* make sure the constructor has been called */
}
private:
unsigned _magicFlag;
}
This "works" because the chances _magicFlag gets allocated where the value is already 1337 is low.
But really, don't do this.
You're getting quite a few responses that basically say, "you shouldn't expect the compiler to help you with this". However, I'd agree with you that the compiler should help with this problem by with some sort of diagnostic. Unfortunately (as the other answers point out), the language spec doesn't help here - once you get to the initializer part of the declaration, the newly declared identifier is in scope.
A while back, DDJ had an article about a simple debugging class called "DogTag" that could be used as a debugging aid to help with:
using an object after deletion
overwriting an object's memory with garbage
using an object before initializing it
I haven't used it much - but it did come in handly on an embedded project that was running into some memory overwrite bugs.
It's basically an elaboration of the "MagicFlag" technique that GMan described.