why is C++ not commonly used in low level code?

Started by
67 comments, last by Washu 12 years, 9 months ago
Would love to see a fight between Linus Torvalds and Alex Stepanov. I think they'd each lose an eye before working out that they agree OO is the root of all evil.
[size="1"]
Advertisement

before working out that they agree OO is the root of all evil.


Then two people would be wrong, yay!

There is nothing wrong with OO done correctly, the 'problem' is the lack of design skills, critial thinking and correctly applying paradigms to solve a problem.

The problem is most people don't have those skills but then again chances are they would write bad code in any paradigm if left to their own devices...

There is nothing wrong with OO done correctly, the 'problem' is the lack of design skills, critial thinking and correctly applying paradigms to solve a problem.

The problem is most people don't have those skills but then again chances are they would write bad code in any paradigm if left to their own devices...


Oh, I agree. I've just always found it funny that many c programmer's arguments against c++ revolve around inheritance, when the guy who designed the STL has pretty much the same opinion! biggrin.gif I'd very much enjoy watching Stepanov and Torvalds direct their arguments at one another in some kind of forum trollocalypse.

In the linked rant (in between attempts at trolling) Torvalds says similar to what you say about lack of skills. Stepanov, for all his hatred of OO, presumeably likes that in c++ you can have a function object whose operator() can be inlined, unlike a c function ptr. So he doesn't mind objects, just OO...... blink.gif

Personally, I think the problem is that 'OO done correctly' means different things in different languages and different problem spaces, which has lead to people having the skills and wanting to apply them, but applying them wrongly for c++ in performance-critical situations. There's a wealth of OO design wisdom out there, and while most of it can be applied to c++ design, not all of it should have been. For example, classical OO literature revolves around using inheritance for polymorphism, which is not always the best way to go in c++ where we have lovely compile-time polymorphism.

(insert obligatory comment about OO being possible in c and the OO argument therefore being irrelevant to this thread anyway - if I didn't someone else would!)
[size="1"]
This opinion that C is 'better than' C++ for various problem domains is rampant in the open source community.
Before making my way back to game development i spent many years writing an irc daemon (ircd). I was often beset with idiots telling me that because i had chosen to write such a program in C++, it simply would not scale, would take all available RAM in the server, that inheritence would make it slow, and other quite frankly stupid arguments.

Needless to say most of these people did not believe that you should choose the right tool for the job. In this particular case, the right tool for the right job, based on my skillsets and the requirements of the application, were C++.

If i was to approach the same problem again today maybe i would not choose C++, but i definitely still would not choose C.
The answer is extremely simple. Three points.
1) Portability. C is the most portable language out there.
2) Simplicity. Most low level code does not require C++ features.
3) Efficiency. C code is often both faster and smaller than C++ code. There's a reason why there are no interesting 1k/4k demos written in C++, because it is shit for size optimized code. :)
The interesting question would be "Why should anyone use C++ in low level code?". :)
Note that with C++ code I actually mean proper OO+exceptions+templates kind of code. Sure, you can write pure C and compile it with C++ compiler and claim that "Oh but it IS valid C++!" but it defeats the whole purpose of the discussion.


This opinion that C is 'better than' C++ for various problem domains is rampant in the open source community.
Before making my way back to game development i spent many years writing an irc daemon (ircd). I was often beset with idiots telling me that because i had chosen to write such a program in C++, it simply would not scale, would take all available RAM in the server, that inheritence would make it slow, and other quite frankly stupid arguments.

Needless to say most of these people did not believe that you should choose the right tool for the job. In this particular case, the right tool for the right job, based on my skillsets and the requirements of the application, were C++.

If i was to approach the same problem again today maybe i would not choose C++, but i definitely still would not choose C.


This is because you don't care about portability. You only wanted your ircd run on your own system.

I myself write code which has to run from routers to super computers, so anything except C is a definite no-go for me, because the code HAS to compile on those machines which run operating systems and CPU and hardware architectures unknown to me. Everything I care about is conforming to C89, POSIX and SUS(Single Unix Specification) standards.



C code is often both faster and smaller than C++ code.


Again, examples please. These spurious claims are making the thread feel like groundhog day.


Note that with C++ code I actually mean proper OO...


You probably don't mean "proper" OO, which is entirely possible in almost any language.


...+exceptions+templates kind of code.


Aargh. Templates do not cause overhead. Having multiple versions of a function for different types is not overhead, if those multiple versions are required. Writing and maintaining several versions of a function does cause overhead - programmer overhead, e.g. time, money and sanity.


Sure, you can write pure C and compile it with C++ compiler and claim that "Oh but it IS valid C++!" but it defeats the whole purpose of the discussion.


Yeah, you can also write C++ code that uses none of the supposedly expensive features above, no additional overhead compared to a C program and all the added benefits of type safety.

There are only two sane reasons to prefer C over C++ in my view - a) there does not exist a well-proven C++ compiler for a given platform or b) the programmers available for the job at an acceptable cost are experienced in C, not C++.

Both are valid real-world reasons. Neither have anything whatsoever to do with the nature of C++, except possibly its younger age than C.

And, as a footnote, all of Linus T's arguments seem to be about C++ programmers, not about C++. But then I haven't written an operating system filled with comments like "// this is a hack, we have no idea how it works" so what do I know?

This is because you don't care about portability. You only wanted your ircd run on your own system.

I myself write code which has to run from routers to super computers, so anything except C is a definite no-go for me, because the code HAS to compile on those machines which run operating systems and CPU and hardware architectures unknown to me. Everything I care about is conforming to C89, POSIX and SUS(Single Unix Specification) standards.





I am sorry but this is an incorrect and hastily entered response. The software in question is extremely popular, in use by many hundreds of networks, and definitely not just designed 'for my own computer'. I myself run a 600 user network on it and there are many other networks of 3000 users and up that use the same software. Maybe you should take a look at the project website (http://www.inspircd.org) and reconsider your kneejerk response to my post.
Moved to the lounge, a more appropriate venue for "C vs C++" or any of the other common examples of X vs Y you can think of.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

Argh. I wrote a long-ish post for almost an hour. Topic moved and the forum itself being rather unfriendly(messing the text layout and indentations), dundun. Since I'm in a hurry I'll just leave these here for now:

Here's a simple example:



C:

#include <stdio.h>

int main(int argc, char *argv[]) {
int i=0;
int j=0;
char name[32];
for(i=0;i<8192;i++) {
printf("Argument count: %d\n", argc);
for(j=0;j<argc;j++) {
printf("Name: %s\n", argv[j]);
}
}
scanf("%32s", (char*)&name);
printf("Hello %s!\n", name);
return 0;
}


C++:

#include <iostream>
#include <string>

int main(int argc, char *argv[]) {
std::string name;
for(int i=0;i<8192;i++) {
std::cout << "Argument count: " << argc << std::endl;
for(int j=0;j<argc;j++) {
std::cout << "Name: " << argv[j] << std::endl;
}
}
std::cin >> name;
std::cout << "Hello " << name << "!" << std::endl;
return 0;
}











results:



[calmis@purpleorange cvscpp]$ g++ main.cpp -o main2 -O0 -Wall -Wextra
[calmis@purpleorange cvscpp]$ gcc main1.c -o main1 -O0 -Wall -Wextra
[calmis@purpleorange cvscpp]$ time echo "Dun-dun Daa" | ./main2 a ab abc abcd abcde abcdef abcdefg > mainCPP.txt

real 0m0.314s
user 0m0.063s
sys 0m0.203s
[calmis@purpleorange cvscpp]$ time echo "Dun-dun Daa" | ./main1 a ab abc abcd abcde abcdef abcdefg > mainC.txt

real 0m0.046s
user 0m0.023s
sys 0m0.000s
[calmis@purpleorange cvscpp]$ wc -c main2
8048 main2
[calmis@purpleorange cvscpp]$ wc -c main1

5213 main1

Size optimizations turned on:


[calmis@purpleorange cvscpp]$ g++ main.cpp -o main2 -Os -s -Wall -Wextra
[calmis@purpleorange cvscpp]$ gcc main1.c -o main1 -Os -s -Wall -Wextra
[calmis@purpleorange cvscpp]$ time echo "Dun-dun Daa" | ./main2 a ab abc abcd abcde abcdef abcdefg > mainCPP.txt

real 0m0.326s
user 0m0.043s
sys 0m0.227s
[calmis@purpleorange cvscpp]$ time echo "Dun-dun Daa" | ./main1 a ab abc abcd abcde abcdef abcdefg > mainC.txt

real 0m0.035s
user 0m0.023s
sys 0m0.000s
[calmis@purpleorange cvscpp]$ wc -c main2
5132 main2
[calmis@purpleorange cvscpp]$ wc -c main1
3508 main1



[/quote]

9.3x faster, some 1.4x smaller.

C functions with void* arguments and a variable to denote the types, and then using switch() to invoke right code(assuming that e.g. 8, 16, 32 and 64 bit ints can share the same code) is more size-efficient than C++ with templates.

I rest my case for now.

Change those std::endl to '\n' and you see a big difference. You are flushing the buffer after every call using std::endl;
Also, to make the code a little closer to the C version, reserve some memory for the string.





#include <iostream>
#include <string>

int main(int argc, char *argv[]) {
std::string name;
name.reserve(32);
for(int i=0;i<8192;i++) {
std::cout << "Argument count: " << argc << '\n';
for(int j=0;j<argc;j++) {
std::cout << "Name: " << argv[j] << '\n';
}
}
std::cin >> name;
std::cout << "Hello " << name << "!" << std::endl;
return 0;
}



C++
real 0m0.042s
user 0m0.030s
sys 0m0.010s

C
real 0m0.029s
user 0m0.020s
sys 0m0.007s

[edit]
Added link about std::endl.

"I can't believe I'm defending logic to a turing machine." - Kent Woolworth [Other Space]

This topic is closed to new replies.

Advertisement