Advertisement

Unnecessary C++ features?

Started by July 13, 2000 07:53 AM
70 comments, last by null_pointer 24 years, 5 months ago
someone said something about declaring variables anywhere in the code is useless...i disagree.

eg:

    void func(int num){    int anArray[100000]; //in C you gotta declare the array at the top    if(num < 10)        return;    //...impl}    


if num is 3, then you just wasted your time allocating all that memory for the array.
POINT: just what I was going to say.

Actually, in your particular example it doesn''t matter. When you declare local variables in a function, it works the same space-wise in C and in C++: the compiler pre-calculates how much memory will be required for all those variables, and allocates all that space on the stack. It does this all at once, so having an int[20] will not be any faster than having an int[2000]--it''ll just take up more stack space.

The DIFFERENCE in performance is that if any of those objects have constructors, they''ll be called when declared. So if you have a hefty constructor, and you need to return before the construction happens, you just saved that time.

But the main reason I really like this feature is because it makes the code so much more readable. I''m having to go through someone else''s work right now and fix bugs/clean it. It''s a C++ project, but he''s old-school so he declared every single friggin'' variable at the top of the function. The function is over 2000 lines long. Guess who''s lost? Guess how many "unreferenced variable" warnings I get every time I toss a bit of code, then have to go fishing for them? (oh, and there''s absolutely no way to tell which variables belong to the function and which belong to the class because he refuses to put m_ in front of member variables).

OK, bitch mode off.

References kick ass. An intern asked me yesterday: I want to return a pointer with this function, but I don''t want them to do anything whacky like delete it or make it point to something else. Voila! Return a reference, not a pointer.
Advertisement
Useless C/C++ features:

- the auto keyword
- class ClassA : private ClassB
- overloading the ~ operator
- MFC =)
- volatile
- static_cast
- iso646.h

Well, some of them have a few uses.. I guess. Oh, on the topic of this thread, I''d like to bitch about operator overloading. I think it''s one of the coolest things about C++, but it really pisses me off when people overload an operator to do something completely unintuitive and/or contradictive to its default nature in the language. In fact I refuse to use iostream simply for that reason.. when I see >> I see a right shift, not stream input!

-RWarden (roberte@maui.net)
Nice thread null_pointer. And good job on staying on track everyone.

In order I remember:

Exceptions expand into a branch, and use stack unwinding to find the catch statement as c++freak said.

I don't use STL much, wrote my own templates for collections / arrays / lists / maps a while ago, and use them since I know what's going on there.

For references, I don't use them either. Of course for operator overloading and such, but I'd rather pass pointers in all other situations.

RWarden - volatile has a very specific function in multithreaded environments, but I wouldn't call it useless. It tells the compiler not to store a value in a register and to reload it from memory on every access. Very important on loops such as:


int gUsers;

void Thread1()
{
while(gUsers)
{
//DO WORK HERE THAT DOESN'T TOUCH gUsers
}
}




Edited by - Jon Juan on July 13, 2000 4:21:10 PM
Hi all.

Quote by c++Freak
quote: Anyways, var1 += var2 is actually, performance wise, better then var1 = var1 + var2, because in the first, you do 1 addition, 1 'get' and one 'set', whereas in the second, you do 1 addition, 2 'get' and one 'set'. Ok tiny performace, but if you do it 1000 times that adds up... right....


I compiled the following using VC++ (SP3):

a = a + 1;
a += 1

and both gave exactly the same code (except using diferent processor registers), when looking at the debuger's disassembly mode:


4: a = a + 1;
0040102F mov eax,dword ptr [ebp-4]
00401032 add eax,1
00401035 mov dword ptr [ebp-4],eax
5: a += 1;
00401038 mov ecx,dword ptr [ebp-4]
0040103B add ecx,1
0040103E mov dword ptr [ebp-4],ecx

So I still preffer "a = a + 1" for readability than "a += 1".

Point, if you are talking about me, please note that I said "in the middle of a statement". Declaring variables in areas other than the top of the function is indeed useful sometimes. But thigs like this are, I think, confusing:

for( int A = 0; A < 10; A++){...}

I rather use:

int A;
for( A = 0; A < 10; A++){...}

By the way, this just my opinion.

Topgoro


Edited by - Topgoro on July 13, 2000 5:10:49 PM
We emphasize "gotoless" programming in this company, so constructs like "goto hell" are strictly forbidden.
Whirlwind, here's a good STL book http://www.amazon.com/exec/obidos/ASIN/0201379260/o/qid=963521005/sr=8-1/ref=aps_sr_b_1_3/104-8520219-0129507 . You can have a look at the SGI STL at http://www.sgi.com/Technology/STL/ , but remember it's not the standard (at least not yet) so some of it wont be support by your version of STL


c++freak:
quote:
...and then, the stack is rewound to the point where the exception was thrown.


C++ doesn't go back to the point the exception was thrown, program flow continues from the end of the catch block (unless you re-throw or don't catch). If a function throws an exception because it can't do it's job properly (missing file, network down, no memory) there's not much point it going back there. If the 'catch' point can fix the problem, you can fake your own resume-after-exception with something like :


while(true)
{
try
{
foo();
break;
}
catch(...)
{
get_resource_for_for();
}
}

but it doesn't happen by default.


Shinkage:
quote:
Personally I think they implemented iterators in STL very well. On another note though, I can't STAND the implementation of templates in Visual C++. I can't even put declarations and definitions in separate files, which really bothers me...


I don't know of any compilers that supported the 'export' keyword yet, but if you just want them in separate files, you could #include the .cpp at the end of the .h. You'll need to remove the #include "stdafx.h" from your .cpp file and exclude it from the build (it'll be included via the .h) for it work in VC.

RWarden:
I don't think auto is a c++ keyword anymore (although it's still supported by most compliers).

static_cast is very useful. It avoids the overhead of dynamic_cast (when you what a pointer really points to), and it doesn't have of the problems with (T*) style casts. As for >>, I can't think of a better way create a typesafe extendable i/o library without adding any extra keywords

Edited by - Wilka on July 13, 2000 5:28:45 PM
Advertisement
quote:
I compiled the following using VC++ (SP3):

a = a + 1;
a += 1

and both gave exactly the same code (except using diferent processor registers), when looking at the debuger''s disassembly mode:


For basic types (e.g. int) the compiler is allowed to generate the same code for both methods, but for user defined types it needs to call the functions you asked for (unless it inlines them, if it does it can see what they do and make them the same) in case they don''t do what they should (i.e. operator+ might work differently to operator+=).
quote: Original post by c++freak

Oh yeah, about exceptions:

[...]

exists, DX isn''t working, GL doesn''t have all the libaries, etc. that will terminate the game/app, so that any performance hit - at that point - will not matter.



Well, I''m a keen supporter of COERENT-PROGRAMMING. That is, is a language gives you a "tool" use it everywhere you can or don''t use it at all.

In the case of exceptions, if I was going to use ''em, I''ll do everywhere I can not just in the initialization "parts" of my applications.

Exceptions are a nice method to "notify events", so they should be used almost everywhere in the code (e.g. instead of using booleans return values in functions).

Of course, this would probably drop down "just a little" the performances, but it will result in a coerent-code.

Personally, in my high-performance applications I don''t use them. Luckily, there are other "coerent-coding" methods to do almost the same thing that exceptions do...


Karmalaa

---[home page] [[email=karmalaa@inwind.it]e-mail[/email]]
/***********/
for( int A = 0; A < 10; A++){...}

I rather use:

int A;
for( A = 0; A < 10; A++){...}
/***********/


The first notation has some advantage over the second one.

In for( int A = 0; A < 10; A++){...},
A has the scope within the for loop alone

whereas in
int A;
for( A = 0; A < 10; A++){...}
A is declared just before the for loop and stays in memory until the end of the function.

The advantage may not be visible for small built in datatypes like int, but when you are going to use a huge user-defined datatype in the for loop, you save a lot of memory by realising it once the for loop is complete.
> Useless:
> - overloading the ~ operator

You need this.

This topic is closed to new replies.

Advertisement