As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Let me start with explaining what I mean with "magic". I will use two examples from Java:
Every class inherits (directly or indirectly) the Object class.
Operator overloading is not supported by Java but the + operator is defined for String objects.
This means that it is impossible to make an implementation of the Object and String classes in pure(*) Java. Now this is what I mean with "magic": to make an implementation of these classes, you will need some special support from the compiler.
What I always liked about C++ is that, as far as I know, there is no such "magic" going on in the STL, i.e. it is possible to implement the STL in pure C++.
Now my question is: is this true? Or are there parts of the STL that cannot be implemented in pure C++ and need some "magic"/special compiler support?
(*) With "pure" I mean without using any class libraries.
in other words, has anything been done to the compiler to allow for a 'special case' the STL needed to work?
No.
It was all implemented as 'pure' C++ code, using the magic of templates.
There has been some work done to compilers to improve the STL (I'm thinking about various optimisations) but otherwise, no, you could write the entire STL if you really wanted. Some people did - STLPort is an implementation that didn't have the backing of any compiler manufacturer.
Like gbjbaanb correctly said, the STL can be implemented in plain C++, without relying on any kind of compiler "magic".
However, if you go digging in the STL source code for your compiler, you'll probably see code that either isn't standard, or which you're not supposed to write yourself.
The STL can be implemented entirely in standard C++, but that doesn't mean compiler writers aren't allowed to improve it occasionally, using compiler-specific extensions. For example, they might insert non-standard code that ensures better error messages, or perhaps works around some flaw in their compiler, or maybe enables special optimizations by using extra features of that specific compiler.
They also consistently use names that you're not allowed to use. For example, template parameters are typically named something like _Type, which, since it starts with an underscore followed by a capital letter, is reserved for the implementation. The standard library is allowed to use them, but you and I are not. So if you were going to write your own STL implementation, you would have to make some minor changes, but that's not because of any magic, just a way to avoid name clashes between the standard library and user code.
As others have said, the STL is implementable in pure standard C++98. What hasn't been said is that the development of the STL was concurrent with the development of the C++ template mechanism, and largely drove the inclusion of certain features. I believe that Argument Dependent Lookup (ADL, aka Koenig Lookup), template template parameters, and default template arguments all came to C++ to serve Stepanov's STL development.
So, with STL, they moved the magic into the language itself. Nice that the standards committee recognized that if those features were useful for what would become the standard library, they might be useful for the rest of us as well!
If by STL you mean only the template portion of the C++ Standard Library, then it is perfectly possible to implement it without any "magic". Whether each given implementation actually uses any "magic" is a different question (there are portions of STL where "magic" would help, but not absolutely required).
Now, if you are talking about the entire C++ Standard Library, then it does indeed have a bit of "magic" in it. The classic example would be the library-provided ::operator new and ::operator delete implementations. We often call them "overloadable" in everyday language, while formally they are replaceable. The C++ language does not offer such functionality to the user. The user cannot write a replaceable function.
Another example would be the offsetof macro (inherited from the C Standard Library). While it is usually implemented in "pure C", the popular implementation is actually illegal from the pedantic point of view (causes undefined behavior). I haven't seen any formally legal implementations of offsetof, so I'm not sure whether they are even possible.
Another example would be (again, inherited from C) the macros for working with variable arguments. They obviously cannot be implemented in pure C or C++.
I'm pretty sure some type_traits require compiler magic, for example has_trivial_constructor, has_virtual_destructor or is_pod.
std::initializer_list needs compiler support and cannot be reimplemented as another class (as far as I know), though I'm not sure if it counts since it's in c++0x.
C++0x is going to standardise some de facto "magic" type traits.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2984.htm
"Additional Type Traits for C++0x"
This contains a few remarks such as "XXXX is believed to require compiler support."
See also
http://gcc.gnu.org/onlinedocs/gcc-4.3.2/gcc/Type-Traits.html#Type-Traits
http://msdn.microsoft.com/en-us/library/ms177194(v=vs.80).aspx
As "gbjbaanb" rightly said, there is no magic involved in the implementation of STL. It is written in pure C++. You could implement it yourself but has been made readily available as a library to make your life simpler.
STL is standard (Standard Template Library). The standard specifies the requirements for STL implementations. From the usage point of view, there is no "magic", no special dependencies you have to take care of. It can be used on any major C++ compilers, on all platforms supported by those compilers.
Related
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Are there any aspects to the C++ programming language where the code is known to be slower than the equivalent C language? Obviously this would be excluding the OO features like virtual functions and vtable features etc.
I am wondering whether, when you are programming in a latency-critical area (and you aren't worried about OO features) whether you could stick with basic C++ or would C be better?
Nothing in the C or C++ language standards specifies the speed of any construct (C++ does specify the time complexity of some operations applied to containers, but that's outside the scope of your question). The speed of the code generated for a given construct depends on the compiler used to compile it, and on the system it runs on.
For a given code construct that's valid C and valid C++ with the same semantics, there's no fundamental reason why either should be faster than the other. But it's likely that one will be faster than the other if the developers of the compiler were a little more clever.
That depends on what you mean by "equivalent". If you compare C's stdio.h with C++'s iostream, stdio.h operations are generally faster (quite a bit faster in some situations). But if you are talking about code written in the subset of C++ that also compiles as valid C, the generated machine code will likely be identical.
For one example, C++ lacks the keyword restrict. Used correctly that sometimes allows the compiler to produce faster code.
it's fairly rare in practice to see benefits from restrict, but it happens,
there are plenty of occasions when a C++ or C compiler can deduce (after inlining) that the necessary conditions for restrict apply, and act accordingly, even though the keyword isn't used,
C++ compilers that are also C compilers might provide restrict or __restrict as an extension anyway.
But occasionally (or quite commonly in some domains), restrict is a really good optimization, which I'm told is one of the reasons for still using Fortran. It's certainly one of the reasons for the strict aliasing rules in both C and C++, which give the same optimization opportunity as restrict for a more limited set of circumstances.
Whether you "count" this depends to an extent what you consider "equivalent code". restrict never changes the meaning of a program that uses it validly -- compilers are free to ignore it. So it's not a stretch to describe the program that uses it (for the eyes of the C compiler) and the program that doesn't (for C++) as "equivalent". The version with restrict took more (perhaps only slightly more) programmer effort to create, since the programmer has to be sure that it's correct before using it.
If you mean, is there a program that is valid C and also valid C++, and has the same meaning in both, but implementations are somehow constrained by the C++ standard to run it slower than C implementations, then I'm pretty sure the answer is "no". If you mean, are there any potential performance tweaks available in standard C but not in standard C++, then the answer is "yes".
Whether you can get any benefit from the tweak is another matter, whether you'd have got more benefit for the same amount of effort with a different optimization available in both languages is another, and whether any benefit is big enough to base your choice of language on is still another. It's laughably easy to interoperate between C and C++ code, so if you have any reason at all to prefer C++, then like any optimization that alters your preferred way of coding, switching to C would normally be something you'd do when your profiler tells you your function is too slow, and not before.
Also, I'm trying to convince myself one way or the other whether the potential for exceptions costs performance, assuming that you never use any type that has a non-trivial destructor. I suspect that in practice it probably can (and that this is a contradiction to the "don't pay for what you don't use" principle), if only because otherwise there'd be no point gcc having -fno-exceptions. C++ implementations bring the cost down pretty low (and it's mostly in rodata, not code), but that doesn't mean it's zero. Latency-critical code may or may not also be binary-size-critical code.
Again it might depend what you mean by "equivalent" code -- if I have to compile my so-called "standard C++ program" using a non-standard compiler (such as g++ -fno-exceptions) in order to "prove" that the C++ code is as good as the C, then in some sense the C++ standard is costing me something.
Finally, the C++ runtime itself has a start-up cost, which is not necessarily identical to the C runtime start-up cost for the "same" program. You can generally hack about to reduce the cost of both by removing things you don't strictly need. But that is effort, implementations don't necessarily do it for you completely every time, so it's not strictly true that in C++ you don't pay for what you don't use. That's the general principle, but achieving it is a quality of implementation issue.
Contrary to what many C programmers like to think, one can often write tighter and faster code in C++ all without having to sacrifice a great deal in design.
I can't think of anything in C++ that is slower than its counterpart in C. Virtual functions NOT excluded.
Does Latency critical mean as fast as possible or does it simply mean that everything has to run in predictable time?
If it is the second case, then the only things that don't run in predictable time are new, delete and try/catch. In embedded programming there are directives to avoid such calls. In other cases, especially in C++11 you might notice some things are faster (std::sort is faster than C's sort() ) and some are marginally slower.
But what you gain over C++ is higher abstraction levels and you don't get the C-style bugs (like the typical malloc() without a corresponding free() )
There is no code in C++ whose direct equivalent in C is faster- or, indeed, more maintainable.
If you're using the language that's the intersection of C and C++, then any difference in performance when compiling that code with a C compiler versus a C++ compiler is purely a quality-of-implementation issue; there's no reason one should be faster than the other.
Of course in the real world, if you're using C++ you program using both the additional features that C++ has over the intersection of C and C++ and using different idioms than you would in C. And conversely, if you're using C, you at least use very different idioms from what you would use in C++, and you may also be using additional features of the modern C language which C++ does not have, like, as Steve mentioned, the restrict keyword, or VLAs or pointer-to-VLA types, or compound literals. These features could give major performance benefits in some situations, but in my experience they're not the reasons most people who choose C over C++ do so.
In my mind, the main difference really is idioms. In C, it's idiomatic to make a linked list by putting the next/prev pointers directly in the structure that's being kept in a list, rather than using a separate wrapper object for the list and list nodes. In C, it's idiomatic to iterate directly over the elements of a string as a character array. In C, it's idiomatic to work with objects that exist entirely in automatic storage whenever possible rather than allocating dynamic storage. And so on. These idiomatic differences are the main ways C code tends to be faster and lighter than C++.
Of course if you want, you can use the same idioms in C++, since most of the language constructs needed for most C idioms exist in the intersection of C and C++. And then you can also use the additional features of C++ when appropriate. But you'll be writing non-idiomatic C++ code, and you might receive a lot of criticism from other C++ programmers...
restrict is a C99 feature which is getting a lot of attention lately by allowing the compiler to perform "previously-fortran-only" optimizations to pointers. It's also the same keyword announced by Microsoft recently to be the underpinnings of the C++AMP specification.
Is that keyword actually in the FCD? If not, is there a specific reason it was omitted?
The only mention of restrict in the C++11 FDIS is on §17.2 [library.c]:
The descriptions of many library functions rely on the C standard library for the signatures and semantics
of those functions. In all such cases, any use of the restrict qualifier shall be omitted.
So restrict is not in C++11.
One argument is that C needs restrict more than C++, because many operations are done with pointers to primitive types and therefore C code has more aliasing problems than C++.
The aliasing rules say that pointers to different types cannot alias, so if the parameters to a function are of different class types they just cannot overlap.
In C++ we also have the valarray family of classes that are supposed to handle arrays of primitive types that are not allowed to alias. Not that it is used much...
Adding yet another way to resolve some aliasing problems, obviously didn't excite the committee enough.
http://herbsutter.com/2012/05/03/reader-qa-what-about-vc-and-c99/
Not only the VC++ team, but also the ISO C++ standards committee, considered adding restrict to VC++ and ISO C++, respectively. Although it was specifically suggested for ISO C++11, it was rejected, in part because it’s not always obvious how it extends to C++ code because C++ is a larger language with more options and we would want to make sure the feature works correctly across the entire language.
Don't think it's in C++1x (unfortunately time has long run out for 0x...!) but at least msvc and g++ support it through __restrict and __restrict__ extensions. (I don't use gcc much, I think that's the correct extension).
To work properly with C++ I feel that we would also need restricted references, not just pointers, maybe along the lines of my question C++ aliasing rules. Not sure if some of these considerations might be holding things up...
I will take a crack at "why not?"
restrict is basically just an assertion that the compiler cannot verify. (Or more precisely, when the compiler can verify it, the assertion itself is not helpful.) This is just not the sort of thing that the C++ committee is going to like. C++ has always tended to assume "sufficiently smart compilers"; heck, look at the hideous performance of the most trivial C++ libraries before the compilers caught up.
I also suspect the committee felt that defining restrict semantics precisely in the presence of all the other C++ features (references, rvalue references, blah blah blah) would be non-trivial.
So, non-trivial to specify + "a sufficiently smart compiler doesn't need it" = NAK.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
Well that may sound like a troll question, but since C++ seems hard to fully master (and I never really knew STL was actually "part" of it), I wanted to know what are the disadvantages to use C instead of C++ when not relying much on OOP.
C++ can have a very much sophisticated syntax sometimes, which is kinda confusing me while trying to use OGRE3D for example...
Non-OO features that C++ has that C does not:
Templates
Function overloading
References
Namespaces
You can use structs and enums without writing struct or enum before every declaration or using typedefs.
Even if you don't define your own classes, using C++'s string and container classes is still often more convenient and safe to work with than c-style strings and arrays.
Type safety (even though some would call it weak)
Exceptions
Variable declarations in conditionals, C99 only has it in for
I'm a big fan of C who over time has become a big fan of C++. One of the big reasons for that is the STL ( the Standard Template Library ) and Boost.
Between the two of them it makes it very easy to write powerful portable applications.
Why C++ is better than C? Besides the obvious list of features, in my opinion the real answer is that there's no good reason to still use C instead of C++. Even if you don't use OOP, you can use it as a better C. Even if you use just once a unique feature of C++ in your program, C++ is already a winner.
On the other hand, there's no disadvantage in using C++: it retains the performance goals of C and it is a quite low level language, while allowing very powerful things. And you will not miss any C feature using C++!
And don't forget the wide user base and the rich libraries and frameworks available.
By the way, C99 has added some interesting features but after a decade there's still very limited compiler support (so you are bound to ANSI C). In the meantime C++ evolved as well and the compiler vendors are committed to providing conforming implementations.
One "feature" that hasn't been mentioned much (but I think is noteworthy) is that the C++ compiler community seems to be willing to go to a lot more work to produce conforming implementations. Back when the standard that eventually became C89/90 was in work, nearly every compiler vendor worked at conforming with the latest drafts of the standard, and (especially when the standard was close to complete) really put a lot of work into conforming as closely as they could.
That's no longer the case. The C99 standard was (obviously enough) completed over a decade ago, but there's still basically only one implementation that makes a serious attempt at conforming with the whole standard (Comeau). A few others (e.g., gcc) have added some C99 features, but are still missing a fair number of others. One (pcc) is in the rather paradoxical position of having added nearly all of the features specific to C99, but doesn't come very close to meeting the requirements of C89/90.
Given the complexity of C++, producing a conforming implementation is a much more difficult task. Despite this, I'd guess there are already more implementations that are at least really close to conforming with C++ 0x (due to be ratified a year or two from now) than with C99 (ratified roughly a decade ago). Just to pick an arbitrary number, I'd expect to see 3 conforming1 implementations of C++0x sooner than 3 conforming implementations of C99 (in fact, I'd almost expect that many the day it's ratified).
Of course, "conforming" in this case means "to a practical degree" -- I'm pretty sure every implementation of C and C++ has at least a few defects that prevents perfect conformance. The same is true for most other languages, the only obvious exceptions being languages that are defined in terms of a particular implementation.
References are done automatically and much safer compared to pointers, the standard library is far more extensive, templates make code extremely customizable and substantially faster and safer. C++ offers fantastic code use/reuse and organization. Also, if you don't rely much on OOP, then you're doing it wrong. There's times when objects are not appropriate, but they're not the majority of scenarios.
One reason to write libraries in C is that it is very easy to use that library across languages since the C ABI is very simple, compared to the name-mangling mess that is C++ ABI.
Creating C interfaces to the C++ libs might be a decent solution, but if you can express your API easily with C syntax, why write it in C++ to begin with?
Many C99 features are very nice, and are still not in C++.
[Note: this is a subjective response but the question itself tends to invoke subjective responses by nature].
C++ is a multi-paradigm language and there's a lot more to it than OOP. However, to suggest it's simply better than C is a bit... bold. :-D In the hands of an experienced C coder, and for the right purposes, C code can be very elegant and simple. Consider the Lua interpreter which is coded in C; it compiles to a very small binary which would have likely been a lot bigger even in the hands of an equally skilled C++ programmer, and is therefore well-suited for embedded use. C generally won't be as safe (ex: implicit casting, requires manual resource cleanup, etc) which is one thing which C++ strives to do a little better than C, but it also won't burden the programmer with awkward casting syntax (in C++ one shouldn't need to cast often, but in C it's quite common), e.g.
On the other hand, and I'm trying to speak very generally, C++ can actually make it easier to write more efficient code, particularly for code that needs to work across multiple types. The qsort vs std::sort benchmarks are a classic example of this and how C++, through templates and inlined function objects, can provide cost-free abstractions. In C one would have to write a separate sorting algorithm for every type by hand or stuff it in a macro to achieve comparable results.
Most C++ programmers who migrated from C never look back. I might be an oddball, but I still find C to be useful for implementing small scale libraries. For a start, it's a bit easier to port and builds super fast. For these kinds of things, I take implicit casting for granted. I would hate to work with any C code on a large scale, however, and have unfortunately have to do this from time to time.
As for specific differences, sepp2k already pointed out a pretty comprehensive list.
You can continue to write essentially C code but compile it as C++ and get the benefit of stronger type checking, and therefore more robust code.
You can then if you wish introduce the useful elements of C++ that have nothing to do with OO, such as a built-in bool, function overloading, and better defined const handling (no need to use macros for literal constant symbols).
It is not even too much of a stretch to using some of the easier to understand and use elements of the standard library such as std::string and iostreams, and even std::vector as a "better array"; you do not have to learn much C++ or understand OOP to take advantage of these improved interfaces.
Between OOP an procedural programming there is an intermediate Object Based Programming, which C++ supports and which is simpler to understand and learn and almost as useful as full OOP. Basically it uses abstract data types rather than full classes and eschews inheritance and polymorphism. To be honest it is what many C++ programmers write in any case.
Other than the upsides that sepp2k noted (and I aggree with) it certainly also has some little downsides that have not directly to do with OO. Come to mind the lack of __VA_ARGS__ for the preprocessor and the context sensitivity. Consider something like:
switch (argc) {
case 1: /* empty statement */;
toto T;
case 2: break;
}
In C, whenever the compiler encounters such a piece of code, and argc and toto are known, this is valid. (Sure we might get a warning for the unitialized T afterwards, whence we use it.)
In C++ this depends on the type toto. If it is a POD, everything is fine (well, as fine as for C). If it has a constructor the code is not valid: jump to case label crosses initialization of 'toto T'.
So in some sense, for C++ you must understand the underlying types to see if a control flow is valid.
D easily interfaces with C.
D just as easily interfaces with C++, but (and it's a big but) the C++ needs to be extremely trivial. The code cannot use:
namespaces
templates
multiple inheritance
mix virtual with non-virtual methods
more?
I completely understand the inheritance restriction. The rest however, feel like artificial limitations. Now I don't want to be able to use std::vector<T> directly, but I would really like to be able to link with std::vector<int> as an externed template.
The C++ interfacing page has this particularly depressing comment.
D templates have little in common with
C++ templates, and it is very unlikely
that any sort of reasonable method
could be found to express C++
templates in a link-compatible way
with D.
This means that the C++ STL, and C++
Boost, likely will never be accessible
from D.
Admittedly I'll probably never need std::vector while coding in D, but I'd love to use QT or boost.
So what's the deal. Why is it so hard to express non-trivial C++ classes in D? Would it not be worth it to add some special annotations or something to express at least namespaces?
Update:
"D has namespace support in the works" from Walter Bright.
FWIW Qt has an actively developed binding for D: http://www.dsource.org/projects/qtd
I think many components in boost are too highly tied to C++ to be portable meaningfully to other languages.
Using e.g. std::vector is possible if you spend the time on writing regular (e.g. namespace-level) functions that forward to the appropriate member functions. Tedious, but affordable (for higher-level components; probably not for std::vector).
Also, I very recently checked in the standard library a sealed array and sealed binary heap implementation that use reference counting, malloc/free, and deterministic destruction instead of garbage collection (see http://www.dsource.org/projects/phobos/browser/trunk/phobos/std/container.d). Other containers will follow. These containers use three specific techniques (described in my upcoming article "Sealed Containers") to achieve deterministic destruction without compromising program safety.
Hopefully sealed containers will obviate any need to link with STL containers, even for tight applications that can't afford garbage collection.
As Hans Passant mentions in a comment, the level of interoperability you want between D and C++ isn't even supported among different C++ compilers. There is a C++ ABI (Application Binary Interface) standard that seems to have some support, but I'm not sure exactly how extensive (Intel, GCC and ARM compilers seem to follow the ABIs). I haven't had a need to use it, and I'm not sure whether or not Microsoft adheres to it for their x86 or x64 compilers (I imagine it might for ia64, since that's where the ABI standard started).
See "Interoperability & C++ Compilers" by Joe Goodman for some details on the C++ ABI.
Maybe Walter Bright can be convinced to support D interoperability with C++ libraries/objects that follow the ABI standard (though I'm not sure where he might prioritize it).
Just for fun I've been interfacing to some C++ code.
That probably won't answer for your question, but I think you (and some folks among the D community) might be interested in some notes I've made then. Here it goes: TechNotes.
I already read the FAQ, and i think maybe this is a subjective question, but i need to ask.
Does anyine knows what exactly (i mean formally) is a C++ language extensions.
I already saw examples, like nvdia CUDA c ext, Avalon transaction-based c++ ext.
So the point is something like a formal definition or so.
thxs anyway.
A language extension is simply anything that goes beyond what the language specification calls for. Your compiler might add new features, like special "min" and "max" operators. Your compiler might define the behavior of division by zero, which is otherwise undefined, according to the standard. It might provide additional parameters for your main function. It might be the incorporation of another language's features, such as allowing C-style variable-sized arrays in C++. It might be a facility for specifying a function's calling convention.
Using a language extension usually makes your code non-portable because when you take your code to another OS, compiler, or even compiler version, the extension may not be available anymore, or its behavior may be different from what you had originally used.
Please see Extensible programming:
Extensible programming is a term used
in computer science to describe a
style of computer programming that
focuses on mechanisms to extend the
programming language, compiler and
runtime environment.
and more to the point, the Extensible syntax section:
This simply means that the source
language(s) to be compiled must not be
closed, fixed, or static. It must be
possible to add new keywords,
concepts, and structures to the source
language(s).