![]() |
| | #1 |
| In the Land of Diddly-Doo Join Date: Jul 2006
Posts: 381
| Deleting an object if the constructor failed. Code: B* A:CreateB(std::string paramStr)
{
B* pB= NULL;
try
{
pB = new pB (paramStr);
}
catch (int result)
{
if (result == OK) // OK == 1
{
m_VectorB.push_back(pB);
}
else if (result == FAILED)
{
delete pB;
pB = NULL;
}
}
return pB;
}
B::B(std::string paramStr)
{
int result = initMembers (paramStr); //returns OK / 1 if successful or FAILED / 0 if failed
throw result ;
}
__________________ ERROR: Brain not found. Please insert a new brain! “Do nothing which is of no use.” - Miyamoto Musashi. Last edited by g4j31a5; 09-15-2009 at 01:54 AM. |
| g4j31a5 is offline | |
| | #2 |
| Guest Join Date: Aug 2001
Posts: 5,034
| First let's clarify what 'delete' means: to invoke the destructor and then release the memory (internally, usually done using free()) associated with the object. Furthermore, only the 'owner' of the object calls 'delete' on an object. If you're assigning the result of 'new' to a raw pointer (very bad idea) then that would be you. Otherwise, it's whatever container you're using to manage it with. So then I suppose the question is "does a destructor get invoked on a partially constructed object?" (eg: when an exception is thrown, but not caught, during the constructor). The answer is 'no' (it will, however, be called on whatever class members were fully constructed up to that point). As far as throwing integers as return values, IMO, the is a very bad design. There are a lot of differing opinions on the matter, but the general consensus is that exceptions should only be thrown from an object in the most extreme situations (eg: 'fatal' errors). On the other hand, exceptions thrown and caught from within the same object is often a useful technique for overcoming complicated control-flow situations, but that's a different matter entirely. |
| Sebastiani is offline | |
| | #3 | |
| The larch Join Date: May 2006
Posts: 3,222
| new does two things: a) allocate memory, b) call constructor. delete does the opposite: a) call destructor, b) deallocate memory. Now if the constructor throws an error, new deallocates the memory and rethrows the exception. Also, when the constructor throws, the object never comes to existence (members initialized so far are destroyed) and therefore it would be an error to invoke the destructor on the zombie. So your attempt to signal success by throwing an exception from a constructor couldn't possibly work. Correct way: Code: B* A::CreateB(std::string paramStr)
{
//no special error handling needed here
//some caller handles allocation/construction failures
B* pB = new pB (paramStr);
//if the previous line didn't throw (= if we get this far in the first place), everything's OK
m_VectorB.push_back(pB);
return pB;
}
B::B(std::string paramStr)
{
int result = initMembers (paramStr); //returns OK / 1 if successful or FAILED / 0 if failed
if (!result) throw some_exception("something is wrong"); //only throw in case of failure
}
__________________ I might be wrong. Quote:
Last edited by anon; 09-15-2009 at 02:48 AM. | |
| anon is offline | |
| | #4 |
| Cat without Hat Join Date: Apr 2003
Posts: 8,492
| Of course, even better would be to have each member initializer in turn use exceptions to signal errors, because the entire point of exceptions is that they propagate upwards automatically.
__________________ All the buzzt! CornedBee"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code." - Flon's Law |
| CornedBee is offline | |
| | #5 |
| C++ Witch Join Date: Oct 2003 Location: Singapore
Posts: 11,320
| I suggest that you read GotW #66: Constructor Failures.
__________________ C + C++ Compiler: MinGW port of GCC Build + Version Control System: SCons + Bazaar Look up a C/C++ Reference and learn How To Ask Questions The Smart Way |
| laserlight is offline | |
| | #6 |
| In the Land of Diddly-Doo Join Date: Jul 2006
Posts: 381
| Thanks for the reply guys @Sebastiani: Well, I know that the 'new' method mallocs and then calls the constructor and 'delete' calls the destructor and then free the memory. What I don't know is how exception works in general. And I thought that the object will be fully created even if I throw an exception in the constructor. I guess I'm wrong. About passing int as an exception, yeah, I know that it's not a good idea. But it is sufficient as of now. BTW, as for assigning 'new' to a raw pointer, I've seen lots of open source libraries do that also. So i thought, why can't I? @anon: OIC, I thought we can throw anything at anytime. My mistake then. BTW, your code didn;t work. I tried this one though and it worked: Code: B* A:CreateB(std::string paramStr)
{
B* pB= NULL;
try
{
pB = new pB (paramStr);
}
catch (int result)
{
pB = NULL;
}
m_VectorB.push_back(pB);
return pB;
}
B::B(std::string paramStr)
{
int result = initMembers (paramStr); //returns OK / 1 if successful or FAILED / 0 if failed
if (result == FAILED)
throw result ;
}
@laserlight: Thanks. Another source of information is always good.
__________________ ERROR: Brain not found. Please insert a new brain! “Do nothing which is of no use.” - Miyamoto Musashi. |
| g4j31a5 is offline | |
| | #7 | |||
| Guest Join Date: Aug 2001
Posts: 5,034
| Quote:
Code: struct fatal
{ };
struct object
{
object( bool chaos )
{
if( chaos )
throw fatal( );
cout << "object( )" << endl;
}
virtual ~object( void )
{
cout << "~object( )" << endl;
}
};
void test( void )
{
object*
ptr = new object( false );
object
obj( true );
}
int main( void )
try
{
test( );
}
catch( ... )
{ }
Quote:
Code: void test( void )
{
object*
ptr;
try
{
ptr = new object( true );
object
obj( true );
}
catch( ... )
{
delete ptr; // whoops!
}
}
You might think you could simply call delete if the exception isn't an std::bad_alloc, but unfortunately, that won't work since it could have originated from anywhere between the try block. The solution, of course, is to follow the RAII strategy: Code: void test( void )
{
std::auto_ptr< object >
ptr( new object( false ) );
object
obj( true );
}
Quote:
| |||
| Sebastiani is offline | |
| | #8 |
| Cat without Hat Join Date: Apr 2003
Posts: 8,492
| Doing exceptions without strictly following RAII principles is just setting yourself up for lots and lots of headaches, and bugs in code paths that are very rarely tested.
__________________ All the buzzt! CornedBee"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code." - Flon's Law |
| CornedBee is offline | |
| | #9 | |
| Malum in se Join Date: Apr 2007
Posts: 3,188
| Quote:
e.g. Code:
class Public_Class {
LPVOID pObject;
// public functions and data go here
Code: Public_Class::Public_Class(){
this->pObject = (LPVOID) new ActualClass();
return;
}
__________________ Until you can build a working general purpose reprogrammable computer out of basic components from radio shack, you are not fit to call yourself a programmer in my presence. This is cwhizard, signing off. Last edited by abachler; 09-16-2009 at 01:44 AM. | |
| abachler is offline | |
| | #10 |
| Cat without Hat Join Date: Apr 2003
Posts: 8,492
| But why not do this? Code: class Public_Class {
class Impl;
boost::scoped_ptr<Impl> m_impl; // or equivalent to scoped_ptr
public:
Public_Class();
~Public_Class();
};
// implementation:
class Public_Class::Impl
{
// ...
};
Public_Class::Public_Class()
: m_impl(new Impl)
{}
Public_Class::~Public_Class()
{} // Empty. It's only out-of-line to force an instantiation location for scoped_ptr's destructor.
__________________ All the buzzt! CornedBee"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code." - Flon's Law |
| CornedBee is offline | |
| | #11 |
| Ex scientia vera Join Date: Sep 2007
Posts: 464
| Not my intention to hijack the topic - but the reason you shouldn't be using new directly with raw pointers with custom objects is more or less because it never goes out of scope, due to the simple fact that it's not allocated on the stack? And using std::auto_ptr solves this for us because when it goes out of scope, it destroys the objects it is encapsulating? Very informative post - still learning how to write proper code in C++.
__________________ "What's up, Doc?" "'Up' is a relative concept. It has no intrinsic value." |
| IceDane is offline | |
| | #12 | |
| Cat without Hat Join Date: Apr 2003
Posts: 8,492
| Quote:
__________________ All the buzzt! CornedBee"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code." - Flon's Law | |
| CornedBee is offline | |
| | #13 | |
| Ex scientia vera Join Date: Sep 2007
Posts: 464
| Quote:
I was actually wondering how I should go about solving a problem, and by surfing this forum, not looking for the solution at all, I stumbled upon it, heh.
__________________ "What's up, Doc?" "'Up' is a relative concept. It has no intrinsic value." | |
| IceDane is offline | |
| | #14 |
| In the Land of Diddly-Doo Join Date: Jul 2006
Posts: 381
| @Sebastiani & CornedBee: RAII? what's that? sorry that's still new to my ear. I swear, the profs have never mentioned that word when I was in college. -_-a @abachler: LPVOID is the same as void*, right? Although it's doable, it's too much of a hassle IMHO. I rarely use void* so that the code can be read better. :P You know, I've also never used auto_ptr. It's not portable IIRC. Maybe I'll try it in the future. As for passing pointers out of scope, I usually does that and control them strictly by myself. So I have to make sure if the object is still alive or not before doing anything to it on different objects. I usually code what came up first in my head. I confess, I suck at designing my codes. :P
__________________ ERROR: Brain not found. Please insert a new brain! “Do nothing which is of no use.” - Miyamoto Musashi. |
| g4j31a5 is offline | |
| | #15 | |
| C++ Witch Join Date: Oct 2003 Location: Singapore
Posts: 11,320
| Quote:
__________________ C + C++ Compiler: MinGW port of GCC Build + Version Control System: SCons + Bazaar Look up a C/C++ Reference and learn How To Ask Questions The Smart Way | |
| laserlight is offline | |
![]() |
| Thread Tools | |
| Display Modes | |
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Deleting object after list removal (C++ visual studio) | RancidWannaRiot | Windows Programming | 2 | 10-20-2005 06:06 PM |
| Question on l-values. | Hulag | C++ Programming | 6 | 10-13-2005 04:33 PM |
| A question about constructors... | Wolve | C++ Programming | 9 | 05-04-2005 04:24 PM |
| deleting dynamic object problem | eth0 | C++ Programming | 17 | 05-19-2004 01:17 PM |
| Array of Pointers + Deleting An Object = Problems | Nereus | C++ Programming | 3 | 03-04-2004 12:16 PM |