Is C++ too complex?
#1 Members - Reputation: 287
Posted 30 November 2012 - 01:42 AM
#2 Members - Reputation: 1396
Posted 30 November 2012 - 02:00 AM
If I wanted to parse a small text file every two hours I would certainly not use C style file IO over iostreams. If the whole purpose of my program were chewing through Gigabytes of text files I would use neither explicitly, I would have a look at flex/bison, Antlr or their friends to see which suited my needs best.
#3 Members - Reputation: 1236
Posted 30 November 2012 - 02:23 AM
C++ is full of subtle and complex features, but they are only "overcomplicated" relative to incompetent users, not relative to their purpose; there are many good reasons to do things in a certain way, and valid use cases for everything you don't like or understand.What's the debate on what parts of c++ improve code, and the other parts that are over complicated and are damaging to code standards.
#5 Members - Reputation: 837
Posted 30 November 2012 - 02:49 AM
dynamically allocated memory in classes vs putting it in structs.
I'm not sure what you mean by that. Maybe stack vs heap ?
I believe he means that member data of a class is either dynamically allocated and referenced with a pointer or else it isn't (in which case it may be global, stack or still dynamically allocated, depending on how the instance of the class was defined).
#7 Members - Reputation: 1396
Posted 30 November 2012 - 02:58 AM
#8 Crossbones+ - Reputation: 5152
Posted 30 November 2012 - 02:58 AM
Classes and structures are exactly the same thing except for default visibility of members and methods. You are asking about 2 unrelated things—whether related information is inside classes or structures does not matter, nor does it matter if it was allocated dynamically or embedded within an encapsulating class/struct. There are combinations of these 2 things suitable for various situations, and there is a time and place for all of these combinations.dynamically allocated memory in classes vs putting it in structs.
It is just common practice to make structures hold “plain old data”, but otherwise there is nothing unique between classes and structures.
The only part of C++ that should be avoided as much as possible is “goto”.
[EDIT]
Damn it Hodgman, beat me to it.
[/EDIT]
L. Spiro
Edited by L. Spiro, 30 November 2012 - 02:59 AM.
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
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums
#9 Members - Reputation: 5801
Posted 30 November 2012 - 03:35 AM
Some examples:
- I use inheritance very infrequently. When I do, I only use single public inheritance and only for the purpose of using virtual dispatch, and I always provide a factory function that creates the actual objects (this is also about the only place where I would write `new' in a program, which is wrapped in a smart pointer right away). The rest of the code is not allowed to know about the specific subclasses.
- I don't use RTTI.
- I only overload operators when defining mathematical classes, and the occasional operator << or >> for streams.
- I don't use trivial standard algorithms (e.g., std::copy), because loops are much easier to read, especially with C++11.
- I don't make complicated template structures, preferring to do some things at run time that could be done at compile time, because it usually helps the clarity of the program.
I am not as adverse to goto as others are here. I learned programming in the 80s and I wrote my share of goto-packed nightmare programs in BASIC. I don't recommend this to anyone, but it helps me tell the difference between a goto that shows poor understanding of loops and function calls (the vast majority of gotos beginners would use) and one that is clear. There are two types of goto that are so useful and so harmless that they were given special names: `break' and `continue'. Using goto to break out of a loop from within a switch statement, for instance, seems perfectly fine to me. I'll write the code in some other way if I think it's more clear, but only then.
Edited by Álvaro, 30 November 2012 - 03:38 AM.
#10 Crossbones+ - Reputation: 1052
Posted 30 November 2012 - 03:42 AM
ome stuff doesn't make much sense anymore in the modern C++11 standard, like having structs and classes, which essentially are the same today. I guess they are still around for backwards compatibility.
I think the nasty bit of C++ isn't the language, it is everything around it. Most toolchains for C++ are old, very old, and seem to be deliberately complicated. I spent so much time crawling through the internet, getting my cross platform build script to make a platform dependent build script to build my project. Yet, my project is still not glued to unit tests.
Comparing it to the java, you have far easier toolchains, designed for modern standards of development. And you almost get platform indipendence for free.
Setting fire to these damn cows one entry at a time!
#11 Members - Reputation: 287
Posted 30 November 2012 - 04:28 AM
#12 Members - Reputation: 378
Posted 30 November 2012 - 05:10 AM
For example fopen, malloc and goto could be replaced with ifstream, new (with smart pointer) and exception respectively.
Whilst the ability to use classic C stuff seems to make the language complex, I actually prefer the way C++ extends rather than reinventing the whole language again from scratch (such as C#).
Kindof like OpenGL is seemingly quite hard to learn for new developers because it still has all the old stuff rather than dropping it all and starting with a brand new graphics API.
#13 Crossbones+ - Reputation: 1147
Posted 30 November 2012 - 06:26 AM
how would you replace the goto in this bit with an exceptionThe parts of C++ that should generally be avoided (unless necessary) is misusing C stuff rather than the C++ alternative.
For example fopen, malloc and goto could be replaced with ifstream, new (with smart pointer) and exception respectively.
Whilst the ability to use classic C stuff seems to make the language complex, I actually prefer the way C++ extends rather than reinventing the whole language again from scratch (such as C#).
Kindof like OpenGL is seemingly quite hard to learn for new developers because it still has all the old stuff rather than dropping it all and starting with a brand new graphics API.
for (int bar =0; bar < 100; ++bar)
{
for(int foo = 0; foo < 100; ++foo)
{
if (foo * bar == 100)
{
goto loopBreak;
}
}
}
loopBreak:
printf("%d", 100);
The code I am presenting is not doing something usefull at all to be honest but imagine a difficult calculation going on over a grid in which if a certain condition is met you need to break out of both loops and continue the rest of the algorithm with the results already calucalted?
#14 Crossbones+ - Reputation: 3517
Posted 30 November 2012 - 06:40 AM
[source lang="cpp"]int doWork(){ for (int bar =0; bar < 100; ++bar) { for(int foo = 0; foo < 100; ++foo) { if (foo * bar == 100) { return 1; } } } return 0;}// ...if (doWork()) printf("%d", 100);[/source]how would you replace the goto in this bit with an exception
Or, use a boolean flag for each loop... works too but it's ugly.
EDIT: I guess foo wasn't the best function name, lol.
Edited by Bacterius, 30 November 2012 - 07:02 AM.
#15 Moderators - Reputation: 13472
Posted 30 November 2012 - 06:46 AM
I'm of the opinion that exceptions as implemented in C++ are too costly to be used in the same fashion as they are in C#/Java. I use exceptions in C#, but never ever use them in C++. </opinion>how would you replace the goto in this bit with an exception
Anyway, as above you can split that work out into a function, or just put your condition into the for loops:
void function()
{
found = false;
for (int bar =0; !found && bar < 100; ++bar)
for(int foo = 0; !found && foo < 100; ++foo)
if (foo * bar == 100)
found = true;
}Pretty much the only time I use goto is when you've got a complex function that's allocating multiple resources and has multiple points of failure, where they all goto a cleanup section at the bottom. However, RAII solves this in C++, so it's not necessary any more, most of the time.[edit]
Out of interests sake, because I assumed they'd all generate pretty much the same Asm, I tested my C++ compiler (MSVC9 /O2) with the above loop+flag, the previously posted function+return, and the original goto-as-double-break variants. In all cases the loop+flag was the slowest, so I'll normalize the results against it and call it's speed 100%.
If the break condition is hit quickly (e.g. foo*bar == 100), then the function+return solution finished in 94% of the time, and the goto in 92% of the time. If the break condition isn't hit (e.g. foo*bar == 99999), then function+return finished in 67% of the time, and goto in 99% of the time...
[edit2]Added a 4th test for throwing a bool to escape the two loops. If the condition isn't met, it weighed in at 103%, but if the condition is met quickly as before, it took 206358% as long...
So, uh, yeah, I'd go with Bacterius' code.
Edited by Hodgman, 30 November 2012 - 07:31 AM.
#16 Members - Reputation: 3328
Posted 30 November 2012 - 06:47 AM
All good answers guys, it was nice to read every single post confirming my biases that there's nothing unnecessary in the language, next time I read an article that has me challenge my assumptions about c++ I'll ignore it.
That is foolish. The articles that challenge our assumptions are the most important for us to read. Too many developers fall into dogmatic faith that what they know is best, ignoring better solutions. This is one of the quickest ways to become a bad programmer.
While there aren't many unnecessary parts of C++ there are many parts that should be avoided, and far more that require great care to use properly. The language itself is a poor option for many programming problems.
#17 Members - Reputation: 2761
Posted 30 November 2012 - 08:06 AM
It's funny, because ,y gut feel puts me in the same position with many constructs. Using dictionaries or regular expressions in Python, for example, is normal but in C++ I tend to avoid them because they're expensive.I'm of the opinion that exceptions as implemented in C++ are too costly to be used in the same fashion as they are in C#/Java. I use exceptions in C#, but never ever use them in C++.
Funny thing is, much of the time such constructs in higher-level languages are implemented using the underlying C++ construct. For instance, Java exceptions in the GCC Java runtime are implemented using exactly the same mechanism as C++ exceptions (it's the same libgcc_s.so file on my system). Any performance barrier is psychological: Java forces you to pay the cost always by design, C++ allows you to pay only for what you use, and you can avoid using exceptions, so you feel guilty about waste.
I am still of the opinion that exceptions are too costly to use for anything but exceptional situations. I limit (but not avoid) their use in C++, avoid Java completely, and use Python mostly for prototyping.
Professional Free Software Developer
#18 Crossbones+ - Reputation: 1052
Posted 30 November 2012 - 08:14 AM
I would say wrong semantic. Since you loop as long as a condition is met, you should need a while loop. Breaking out of a for loop is a strong indicator for that.The code I am presenting is not doing something usefull at all to be honest but imagine a difficult calculation going on over a grid in which if a certain condition is met you need to break out of both loops and continue the rest of the algorithm with the results already calucalted?
It is a bit nitpicky, but from a theoretical computer science stand point, for loop with a break statement is wrong. A for loop is intended to repeat the internal statement for a known amount. Therefore a for loop can be expanded by repeating the line of code by x amount of time.
A while loop is very different, each while loop has a variance and invariance which you can use to proof your loop aborts, and with the invariance you can proof that your loop calculates what it should.
</detail>
I am sure there is a freak case where a goto statement makes more sense and is more readable than any other solution, But I have yet to see a good example for it.
You can live a happy and productive life writing clean code without ever using a goto statement.
Edited by Bluefirehawk, 30 November 2012 - 08:14 AM.
Setting fire to these damn cows one entry at a time!
#19 Members - Reputation: 2761
Posted 30 November 2012 - 08:36 AM
In C++. The assertion is not transitive to C.I am sure there is a freak case where a goto statement makes more sense and is more readable than any other solution, But I have yet to see a good example for it.
You can live a happy and productive life writing clean code without ever using a goto statement.
Professional Free Software Developer
#20 Moderators - Reputation: 13472
Posted 30 November 2012 - 09:17 AM
Yeah I get the same feelings, in C# a dictionary is common for me, but I never use std::map in C++, and a hash-table is almost always implemented on top of a flat array... but this is because I'm writing real-time systems in C++ and bloated tools in C#.It's funny, because ,y gut feel puts me in the same position with many constructs. Using dictionaries or regular expressions in Python, for example, is normal but in C++ I tend to avoid them because they're expensive.
No, exceptions in C++ are a fundamentally different construct than exceptions in Java, they just happen to share terminology. Plus most C++ compilers suck at implementing their flavour of them, while the JVM is good at it's flavour. If you port my benchmarks to Java, there's no way the throw version of the double-break idiom will be 2000x slower than the other implementations.Any performance barrier is psychological: Java forces you to pay the cost always by design, C++ allows you to pay only for what you use, and you can avoid using exceptions, so you feel guilty about waste.
Edited by Hodgman, 30 November 2012 - 09:24 AM.






