goto

This is a discussion on goto within the C++ Programming forums, part of the General Programming Boards category; (I never tend to make sure examples are 100% correct, since they are not suppose to be used just to ...

  1. #16
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    (I never tend to make sure examples are 100% correct, since they are not suppose to be used just to give the very general idea)
    It is always better to use existing things, but knowing how they general work is a plus as well. Managing memory is always an issue in C++.
    My point is that C++ offers a way to automatically clean memory, unlike C. That mechanism is destructors. And you can simply wrap around a class on existing classes that will handle the dynamical allocation/de-allocation and you won't have to worry about them. Smart pointers can be a result of the above.

  2. #17
    Registered User
    Join Date
    Feb 2003
    Posts
    595
    Quote Originally Posted by brewbuck View Post
    In other words, it can produce a situation where names are in scope but the objects they refer to are uninitialized.
    I hadn't thought about that. Thanks.

    Quote Originally Posted by Sebastiani View Post
    Whatever you do, though, be sure to always use smart-pointers, and generally speaking, RAII techniques. There's absolutely no excuse for managing raw pointers "by hand"...EVER!!!
    Too bad this is not mentioned in school.

    I understand that only one std::auto_ptr at a time may point to a particular object. But please clarify something for me. When a particular auto_ptr is reassigned to point to a new object, is the object it previously pointed to automatically deleted? e.g.:
    Code:
      ...
      auto_ptr<int> p;
      for( int i = 0; i < 5; ++i ) {
        p = auto_ptr<int>(new int);
        *p = i;
        cout << *p << endl;
      }
    ...
    is that leaking memory or is each int automatically deleted on the next iteration.

  3. #18
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,794
    Quote Originally Posted by R.Stiltskin
    When a particular auto_ptr is reassigned to point to a new object, is the object it previously pointed to automatically deleted?
    Yes, it is.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #19
    Registered User
    Join Date
    Feb 2003
    Posts
    595
    Quote Originally Posted by laserlight View Post
    Yes, it is.
    Thanks.

  5. #20
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,246
    Quote Originally Posted by cyberfish View Post
    I thought GCC won't even allow that. I don't think it allows goto's to fly over initializations (or even declarations?)
    gcc outright forbids it. VC9 does not even warn.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  6. #21
    Registered User
    Join Date
    Oct 2006
    Posts
    2,454
    Quote Originally Posted by laserlight View Post
    Yes, it is.
    unless you explicitly call std::auto_ptr::release() before resetting the pointer.

    one idea I had was to put your whole function inside a try block, and when it's time to return, throw an exception. in the catch block, you can delete all your pointers. just make sure you initialize them to NULL when you declare them, and only delete them if they are not NULL, and your problem is solved

  7. #22
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,246
    Quote Originally Posted by Elkvis View Post
    unless you explicitly call std::auto_ptr::release() before resetting the pointer.

    one idea I had was to put your whole function inside a try block, and when it's time to return, throw an exception. in the catch block, you can delete all your pointers. just make sure you initialize them to NULL when you declare them, and only delete them if they are not NULL, and your problem is solved
    That will work, but IMHO it's a terrible abuse of exceptions.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  8. #23
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,794
    Quote Originally Posted by Elkvis
    one idea I had was to put your whole function inside a try block, and when it's time to return, throw an exception. in the catch block, you can delete all your pointers. just make sure you initialize them to NULL when you declare them, and only delete them if they are not NULL, and your problem is solved
    That feels like an abuse of exceptions to me. It constrains the pointers to have a scope that may be wider than desirable, and in the end is really just a poorly disguised goto, but one that is possibly more expensive.

    EDIT:
    Quote Originally Posted by Elkvis
    unless you explicitly call std::auto_ptr::release() before resetting the pointer.
    If you call release(), then the auto_ptr would not be pointing to any object, so there is no "unless".
    Last edited by laserlight; 12-30-2009 at 11:18 AM.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #24
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Quote Originally Posted by brewbuck View Post
    That will work, but IMHO it's a terrible abuse of exceptions.
    Exceptions can be quite useful flow-control mechanisms, actually (or maybe you meant that they just shouldn't be used to replace RAII, in which case I definitely agree). My Huffman compressor, for example, throws flow-control exceptions (that are caught internally, of course) originating several function calls deep. That way, I don't have to constantly check return values, which simplifies the program logic enormously.

  10. #25
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,246
    Quote Originally Posted by Elkvis View Post
    unless you explicitly call std::auto_ptr::release() before resetting the pointer.

    one idea I had was to put your whole function inside a try block, and when it's time to return, throw an exception. in the catch block, you can delete all your pointers. just make sure you initialize them to NULL when you declare them, and only delete them if they are not NULL, and your problem is solved
    You can delete NULL pointers.
    bit∙hub [bit-huhb] n. A source and destination for information.

  11. #26
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,246
    Quote Originally Posted by Sebastiani View Post
    Exceptions can be quite useful flow-control mechanisms, actually (or maybe you meant that they just shouldn't be used to replace RAII, in which case I definitely agree). My Huffman compressor, for example, throws flow-control exceptions (that are caught internally, of course) originating several function calls deep. That way, I don't have to constantly check return values, which simplifies the program logic enormously.
    There are some situations where that's probably ok, without seeing your code I can't really tell. Boost::Spirit uses exceptions to implement backtracking, which on the one hand is very elegant at the code level, but on the other hand you really have no idea how exceptions are implemented by the compiler and runtime, and throwing an exception could be very lightweight on one platform and a HUGE expense on another.

    Once you've taken that plunge and coded your entire design around exceptions it would be a huge effort to go back on that decision, perhaps to the level of a complete rewrite.

    My philosophy is that an exception should only be thrown when something has gone wrong in a way that should not normally happen (and that doesn't include "every type of error" since some errors are expected to happen during normal use), and that try-catch blocks should only be used in those locations where the exception is dealt with, never for resource management (you can boil this rule down to "never re-throw"). There are very rare situations where you need to do something weird, and of course, everyone is free to do what they want.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  12. #27
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,246
    Quote Originally Posted by brewbuck
    My philosophy is that an exception should only be thrown when something has gone wrong in a way that should not normally happen (and that doesn't include "every type of error" since some errors are expected to happen during normal use)
    I disagree; I think it's a bad idea to mix exceptions and error codes in an application. Otherwise you end up with code that looks like:

    Code:
    try 
    {
        int rc = foo();
        if(!success(rc))
            // handle error
    }
    catch(something)
    {
        // handle error
    }
    bit∙hub [bit-huhb] n. A source and destination for information.

  13. #28
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,246
    Quote Originally Posted by bithub View Post
    I disagree; I think it's a bad idea to mix exceptions and error codes in an application. Otherwise you end up with code that looks like:

    Code:
    try 
    {
        int rc = foo();
        if(!success(rc))
            // handle error
    }
    catch(something)
    {
        // handle error
    }
    I've never ended up with code that looked like that. In most/all cases, the exceptions are of a different ilk than the normal errors and as such would not even be handled at the same layer as the "normal" error codes. I'd say that 90% of the time, my exceptions are handled within a function call or two of main(), not deep down in the code.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  14. #29
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Quote Originally Posted by brewbuck View Post
    There are some situations where that's probably ok, without seeing your code I can't really tell. Boost::Spirit uses exceptions to implement backtracking, which on the one hand is very elegant at the code level, but on the other hand you really have no idea how exceptions are implemented by the compiler and runtime, and throwing an exception could be very lightweight on one platform and a HUGE expense on another.

    Once you've taken that plunge and coded your entire design around exceptions it would be a huge effort to go back on that decision, perhaps to the level of a complete rewrite.

    My philosophy is that an exception should only be thrown when something has gone wrong in a way that should not normally happen (and that doesn't include "every type of error" since some errors are expected to happen during normal use), and that try-catch blocks should only be used in those locations where the exception is dealt with, never for resource management (you can boil this rule down to "never re-throw"). There are very rare situations where you need to do something weird, and of course, everyone is free to do what they want.
    Well, it may be true that on some systems exceptions can be expensive, but I think for the general case the overhead is acceptable. Anyway, they are a ubiquitous aspect of C++ programming these days - I certainly wouldn't design without them.

    As far as using them only for serious errors, I agree that it makes a good rule of thumb, but on the other hand, if it helps simplify things elsewhere - why not? Make the most of the tools at your disposal, and all.

  15. #30
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,596
    Whatever you do, though, be sure to always use smart-pointers, and generally speaking, RAII techniques. There's absolutely no excuse for managing raw pointers "by hand"...EVER!!!
    Keep in mind this functionality is not free. Raw pointers when handled correctly suffice in situations where the 'shared-ness' is not needed or cumbersome. Some game design books talk about using all smart pointers but most talk about using raw pointers and shared's only when absolutely necessary. Shared pointers are notoriously slower (obviously) and this might make or break some projects. However these pointers should not be created in performance critical loops but even using pre-created boost::weak_ptr's requires a call to lock(). You must check the result of lock() prior to using the returned shared_ptr and then branch execution based on the result. For me it is an issue of both and. I definitely see the benefit of smart pointers in production code and have written several containers and classes that use it, but I also see the complexity that they do add. Even boost's implementation, although quite simple once you get used to it, is not all that straightforward. The documentation for them as well is hideous. It took me some time to figure out how to force the pointers to go out of scope b/c the documentation was so unclear. Another issue I have with boost is that it is templated. I realize it has to be but the problem is that templates cause all versions of Visual Studio Intellisense to just about croak. In my experience MSVS will rarely, if ever, provide any Intellisense past weak_ptr::lock() and rarely shows anything for boost::shared_ptr. I realize this is MSVS's fault as it pertains to templates but for the time being it does make working with them, and boost, a pain.

    Another issue I have with boost has to do with the templates. I realize the only way to create a library such as boost is to use templates but this makes using them in projects with multiple DLLs a major issue. You can't return boost::weak_ptr's or boost::shared_ptr's across a DLL boundary. What you end up with is a system which resides in a DLL which either hands out handles to the objects or hands out raw pointers to them. Handing out raw pointers here is a very bad idea indeed since if delete is called on said pointers and those pointers were created in the DLL, the CRT of the caller will be pretty much hosed. So you will end up passing out handles to boost::shared_ptr's that really do nothing. Since you are using handles you might as well store raw pointers inside the container and forego boost altogether. Boost is fine when used in the same module but cannot be used effectively across multiple modules even using the PIMPL idiom - which you must do or you will get a warning similar to: clients of xxx must have a dll-interface to access templated member<X> Of course this type of system could be re-factored so it actually factories out the object in the CRT of the caller instead of the DLL but it's just an illustration of some issues.
    Last edited by VirtualAce; 12-30-2009 at 04:23 PM.

Page 2 of 3 FirstFirst 123 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. add,view=ok, search,edit got error... help!
    By private0430 in forum C Programming
    Replies: 4
    Last Post: 09-27-2009, 01:36 PM
  2. temperature sensors
    By danko in forum C Programming
    Replies: 22
    Last Post: 07-10-2007, 07:26 PM
  3. Does goto have a glitch or...?
    By Blackroot in forum C++ Programming
    Replies: 9
    Last Post: 02-18-2006, 09:40 AM
  4. helpppp
    By The Brain in forum C Programming
    Replies: 1
    Last Post: 07-27-2005, 07:05 PM
  5. Need some help with a basic tic tac toe game
    By darkshadow in forum C Programming
    Replies: 1
    Last Post: 05-12-2002, 04:21 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21