Jump to content

  • Log In with Google      Sign In   
  • Create Account


To goto or not to goto?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
93 replies to this topic

Poll: To goto or not to goto? (149 member(s) have cast votes)

How often do you use goto statements?

  1. Never (92 votes [61.74%])

    Percentage of vote: 61.74%

  2. Very rarely (43 votes [28.86%])

    Percentage of vote: 28.86%

  3. Occasionally (9 votes [6.04%])

    Percentage of vote: 6.04%

  4. Quite often (1 votes [0.67%])

    Percentage of vote: 0.67%

  5. I have made it my quest to use them at least 5 times in each function (2 votes [1.34%])

    Percentage of vote: 1.34%

  6. The language I use doesn't have this keyword (2 votes [1.34%])

    Percentage of vote: 1.34%

Vote Guests cannot vote

#41 szecs   Members   -  Reputation: 2102

Like
0Likes
Like

Posted 09 August 2011 - 06:28 AM

Are you guys serious? Where/what is that complexity you are referring to all the time???

Sponsor:

#42 YellPika   Members   -  Reputation: 142

Like
0Likes
Like

Posted 09 August 2011 - 06:32 AM

While I'm at it, I might as well add one more. Since we're using the goto for a quick and dirty exit, why not a return statement then?

loopFuncWithNiceName();
// whatever came after...
// ...

void loopFuncWithNiceName()
{

  for (int i=0; i<n; ++i) {
    switch (some_array[i]) {
      case 0:
        //...
        break;
      case 1:
        if (some_condition())
          return;// DONE!!!
        break;
      //...
    }
  }
}


#43 SillyCow   Members   -  Reputation: 849

Like
0Likes
Like

Posted 09 August 2011 - 06:45 AM

Well, the title says it all I guess :)


goto | (! goto) = goto.

Since I don't like gotos I would have to say: "To goto and not to goto"

My new android game : Enemies of the Crown

My previous android game : Killer Bees


#44 elondon   Members   -  Reputation: 242

Like
4Likes
Like

Posted 09 August 2011 - 07:00 AM

If you used a goto in production code I would fire you on the spot.



What a ridiculous statement. I can't imagine you're actually a manager. I've never used a GoTo statement in production code - but I'd certainly hate to work for someone who would fire me if I used a construct they don't like especially without examining the context.


"For any absurd set of thinking, you can probably find a non-zero percentage of the population who is utterly convinced of its truth."

#45 luca-deltodesco   Members   -  Reputation: 637

Like
1Likes
Like

Posted 09 August 2011 - 08:03 AM

While I'm at it, I might as well add one more. Since we're using the goto for a quick and dirty exit, why not a return statement then?

loopFuncWithNiceName();
// whatever came after...
// ...

void loopFuncWithNiceName()
{

  for (int i=0; i<n; ++i) {
    switch (some_array[i]) {
      case 0:
        //...
        break;
      case 1:
        if (some_condition())
          return;// DONE!!!
        break;
      //...
    }
  }
}


Because using a return doesn't give you the opportunity to do any cleaning up before the exit

#46 Cornstalks   Crossbones+   -  Reputation: 6974

Like
0Likes
Like

Posted 09 August 2011 - 10:15 AM


While I'm at it, I might as well add one more. Since we're using the goto for a quick and dirty exit, why not a return statement then?

loopFuncWithNiceName();
// whatever came after...
// ...

void loopFuncWithNiceName()
{

  for (int i=0; i<n; ++i) {
    switch (some_array[i]) {
      case 0:
        //...
        break;
      case 1:
        if (some_condition())
          return;// DONE!!!
        break;
      //...
    }
  }
}


Because using a return doesn't give you the opportunity to do any cleaning up before the exit

I think one of the big problems with this discussion is that there are some assumptions we are each making, but we're not making the same assumptions. For myself, I like C++ and RAII, so I shouldn't really need to do any cleaning up before the exit. However, in other languages or situations, RAII may not be available.

Anyway, I've never used a goto in any of my code, and I don't see myself using it in the future either.
[ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

#47 sindisil   Members   -  Reputation: 373

Like
2Likes
Like

Posted 09 August 2011 - 03:51 PM

I do a lot of C programming.

In C, goto is a good way to handle the cleanup code paths in a function, in much the same way that exceptions might be used in a language that supports exceptions.

Beyond that, goto is very rarely useful to break out of an inner loop.

The whole "never a goto" religion is rather sad. As with virtually any other language feature, they can be misused. Likewise, as with virtually any other language feature, they have their place.

#48 wack   Members   -  Reputation: 1267

Like
0Likes
Like

Posted 09 August 2011 - 05:50 PM

Wow, this goto thing has to be the most discussed non-issue in programming during the last 20 years or so.

#49 Codarki   Members   -  Reputation: 462

Like
1Likes
Like

Posted 11 August 2011 - 04:31 AM

I think the ones against goto always use the worst examples of gotos.

And for that reason, here is an example where I personally think it makes good sense to use goto statements (like a replacement for a small inline function):
static MyClass*MyClass::createInstance(void)
{
	MyClass*inst=null;

	if(!(inst=new MyClass()))
    	return null;
	if(!(inst->object1=new Object1()))
    	goto FAILED;
	if(!(inst->object2=new Object2()))
    	goto FAILED;
	if(!(inst->object3=new Object3()))
    	goto FAILED;
	if(!(inst->object4=new Object4()))
    	goto FAILED;

	return inst;

	FAILED:
	{
    	delete inst->object1;
    	delete inst->object2;
    	delete inst->object3;
    	delete inst->object4;
    	delete inst;

    	return null;
	}
}


I think you'r example for goto is pretty bad. How can the allocation of those objects fail without throwing an exception?

static MyClass* MyClass::createInstance()
{
	MyClass* inst = new MyClass();

	if (inst)
	{
    	bool failed = !(inst->object1 = new Object1());
    	if (!failed)
        	failed |= !(inst->object2 = new Object2());
    	if (!failed)
        	failed |= !(inst->object3 = new Object3());
    	if (!failed)
        	failed |= !(inst->object4 = new Object4());

    	if (failed)
    	{
        	delete inst->object1;
        	delete inst->object2;
        	delete inst->object3;
        	delete inst->object4;
        	delete inst;
        	inst = 0;
    	}
	}
 
	return inst;
}

If we use C++, lets write C++. Constructors and destructors and all.

MyClass::MyClass()
: object1(new Object1)
: object2(new Object2)
: object3(new Object3)
: object4(new Object4)
{
}

MyClass::~MyClass()
{
	delete object1;
	delete object2;
	delete object3;
	delete object4;
}

static MyClass* MyClass::createInstance()
{
	return new MyClass();
}
I'd go even further and use std::unique_ptr, so you don't even have to write the destructor.

#50 rip-off   Moderators   -  Reputation: 8068

Like
0Likes
Like

Posted 11 August 2011 - 05:00 AM

If we use C++, lets write C++. Constructors and destructors and all.
...
I'd go even further and use std::unique_ptr, so you don't even have to write the destructor.

You should use std::unique_ptr anyway. In your current code, if Object[2..4] throws during construction the earlier objects will leak.

The alternative is:
MyClass::MyClass()
: 
    object1(0),
    object2(0),
    object3(0),
    object4(0)
{
    try 
    { 
        object1 = new Object1;
        object2 = new Object2;
        object3 = new Object3;
        object4 = new Object4;
    } 
    catch(...)
    {
        delete object4;
        delete object3;
        delete object2;
        delete object1;
        throw;
    }
}
Ugh.

#51 Codarki   Members   -  Reputation: 462

Like
0Likes
Like

Posted 11 August 2011 - 06:27 AM

You should use std::unique_ptr anyway. In your current code, if Object[2..4] throws during construction the earlier objects will leak.

The alternative is:
...
Ugh.


You are right, I made silly incorrect example (with syntax errors) to criticize some other example. Ofcourse one should use RAII, which solves everything. One could even make the Object[1..4] to be members and not heap allocated, thus reducing the problem to:

MyClass::MyClass()
{
}


#52 Slavik81   Members   -  Reputation: 360

Like
0Likes
Like

Posted 11 August 2011 - 02:35 PM

I think you'r example for goto is pretty bad. How can the allocation of those objects fail without throwing an exception?

http://stackoverflow.com/questions/550451/will-new-return-null-in-any-case

#53 Trienco   Crossbones+   -  Reputation: 2088

Like
0Likes
Like

Posted 11 August 2011 - 10:34 PM

I think you'r example for goto is pretty bad. How can the allocation of those objects fail without throwing an exception?

http://stackoverflow...ull-in-any-case


Which boils down to "because your compiler is old and pre-standard" or "because you explicitely used new(nothrow)". That is relatively unlikely, at least compared to programmers still thinking that if their new ever fails, it will return 0 (heck, every day at work I'm staring at those pointless != NULL checks).
f@dzhttp://festini.device-zero.de

#54 Slavik81   Members   -  Reputation: 360

Like
0Likes
Like

Posted 12 August 2011 - 01:06 AM

Which boils down to "because your compiler is old and pre-standard" or "because you explicitely used new(nothrow)". That is relatively unlikely, at least compared to programmers still thinking that if their new ever fails, it will return 0 (heck, every day at work I'm staring at those pointless != NULL checks).

What do they do if it is NULL? It would be a huge pain to handle allocation failure gracefully at every instance it could occur.

#55 NightCreature83   Crossbones+   -  Reputation: 2703

Like
0Likes
Like

Posted 12 August 2011 - 08:23 AM


I think you'r example for goto is pretty bad. How can the allocation of those objects fail without throwing an exception?

http://stackoverflow...ull-in-any-case


Which boils down to "because your compiler is old and pre-standard" or "because you explicitely used new(nothrow)". That is relatively unlikely, at least compared to programmers still thinking that if their new ever fails, it will return 0 (heck, every day at work I'm staring at those pointless != NULL checks).

Those null checks however could well be valid if your new operator is overriden as the allocation at that point doesn't need to throw when it is not allocating. Most industry places actually don't use execeptions and hence rely on the fact that a valid allocation returns a null pointer.
Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, Mad Max

#56 Tachikoma   Members   -  Reputation: 552

Like
0Likes
Like

Posted 12 August 2011 - 10:19 AM

Which boils down to "because your compiler is old and pre-standard" or "because you explicitely used new(nothrow)". That is relatively unlikely, at least compared to programmers still thinking that if their new ever fails, it will return 0 (heck, every day at work I'm staring at those pointless != NULL checks).


What do they do if it is NULL? It would be a huge pain to handle allocation failure gracefully at every instance it could occur.


The only situation i can think of where new(std::nothrow) should be used is within exception objects (i.e. classes that are based on std::exception, and so on). This may also warrant the use of goto for garbage collection when encountering a == NULL result.
Latest project: Sideways Racing on the iPad

#57 way2lazy2care   Members   -  Reputation: 782

Like
0Likes
Like

Posted 12 August 2011 - 11:04 AM


I think the ones against goto always use the worst examples of gotos.

And for that reason, here is an example where I personally think it makes good sense to use goto statements (like a replacement for a small inline function):
static MyClass*MyClass::createInstance(void)
{
	MyClass*inst=null;

	if(!(inst=new MyClass()))
    	return null;
	if(!(inst->object1=new Object1()))
    	goto FAILED;
	if(!(inst->object2=new Object2()))
    	goto FAILED;
	if(!(inst->object3=new Object3()))
    	goto FAILED;
	if(!(inst->object4=new Object4()))
    	goto FAILED;

	return inst;

	FAILED:
	{
    	delete inst->object1;
    	delete inst->object2;
    	delete inst->object3;
    	delete inst->object4;
    	delete inst;

    	return null;
	}
}


I think you'r example for goto is pretty bad. How can the allocation of those objects fail without throwing an exception?

static MyClass* MyClass::createInstance()
{
	MyClass* inst = new MyClass();

	if (inst)
	{
    	bool failed = !(inst->object1 = new Object1());
    	if (!failed)
        	failed |= !(inst->object2 = new Object2());
    	if (!failed)
        	failed |= !(inst->object3 = new Object3());
    	if (!failed)
        	failed |= !(inst->object4 = new Object4());

    	if (failed)
    	{
        	delete inst->object1;
        	delete inst->object2;
        	delete inst->object3;
        	delete inst->object4;
        	delete inst;
        	inst = 0;
    	}
	}
 
	return inst;
}

If we use C++, lets write C++. Constructors and destructors and all.


You realize that your code is slower than the example using gotos and arguably less readable. You have an extra variable, 4 extra assignments, and an extra branch vs the goto code

edit: it appears to also fall into the trap of "The Phony Goto Debate" in the Code Complete article. tldr being that using a trivial piece of code you'd never put goto in anyway will more obviously paint goto in a bad light or vice versa the performance gains by using goto may be trivial as the example is trivial to begin with. It's a losing argument from both sides.

#58 Cornstalks   Crossbones+   -  Reputation: 6974

Like
0Likes
Like

Posted 12 August 2011 - 03:12 PM


static MyClass* MyClass::createInstance()
{
	MyClass* inst = new MyClass();

	if (inst)
	{
    	bool failed = !(inst->object1 = new Object1());
    	if (!failed)
        	failed |= !(inst->object2 = new Object2());
    	if (!failed)
        	failed |= !(inst->object3 = new Object3());
    	if (!failed)
        	failed |= !(inst->object4 = new Object4());

    	if (failed)
    	{
        	delete inst->object1;
        	delete inst->object2;
        	delete inst->object3;
        	delete inst->object4;
        	delete inst;
        	inst = 0;
    	}
	}
 
	return inst;
}

If we use C++, lets write C++. Constructors and destructors and all.


You realize that your code is slower than the example using gotos and arguably less readable. You have an extra variable, 4 extra assignments, and an extra branch vs the goto code


Ummmm... Premature optimization? While the code he proposed wasn't what I would call an improvement on the original code, you do realize that the most expensive operation would be the memory allocation, which is something you would try to avoid at all costs if possible in a time critical, tight loop, and the memory allocation should be the focus, if one is going to get into optimizing, and not on the more trivial things, right? The other argument you have (less readable) may be acceptable, however.

Anyway, I'm going to stop here because I don't want to get side tracked and have anyone start flaming or trolling. It was interesting to see everyone else's views on goto.
[ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

#59 Trienco   Crossbones+   -  Reputation: 2088

Like
0Likes
Like

Posted 13 August 2011 - 12:18 AM

Those null checks however could well be valid if your new operator is overriden as the allocation at that point doesn't need to throw when it is not allocating. Most industry places actually don't use execeptions and hence rely on the fact that a valid allocation returns a null pointer.


On projects like that I can see your point, but I assure you, nobody is overriding new or using an old compiler on this project (or actually does anything _useful_ as a result of this check), for example this kind of thing just makes you want to scream:

constructor()
{
  if ( (subobjectA = new ObjectA) == NULL)
	return;

  if ( (subobjectB = new ObjectB) == NULL)
	return;

   ...do more stuff
}

f@dzhttp://festini.device-zero.de

#60 L. Spiro   Crossbones+   -  Reputation: 12978

Like
0Likes
Like

Posted 13 August 2011 - 07:32 AM

I have invented several new programming languages and I never even include the goto keyword.
There is always a more graceful way to handle failures, especially with destructors. C may not have destructors, but there are still ways to securely handle failures, devoid of human faults.


L. Spiro
It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS