Even Listing 2 is not correct. In the assignment operator, if new fails, this will leave “a” pointing to deleted storage. And the performance is not optimal, because in the assignment operator and the copy constructor objects will be default initialized, just to overwrite them in the next step. Instead, uninitialized storage should be allocated and then initialized with their final state. The standard library has the nice uninitialized_fill algorithm for that purpose…
C++ is a great source obfuscation tool. Needing to write custom constructors and copy operator for things as basic as arrays is awful. Does it really makes sense ?
in this example, the idea that you can assign the contents of a pointer when assigning a pointer are causing the ‘novice’ imagined by the article problems.
However, there might be equally occasions when assigning the pointer – and not creating a copy of the contents – is precisely what you meant to do.
I am not convinced that this article is strong on the usefulness factor (to myself), but I am sure that C++ is and remains a very very useful tool.
Of course, one would never actually write an array class like the one given in the example. Intead, you’d just use the STL vector. For static arrays you can use the boost array class, and for multidimensional arrays the boost multidimensional array class is excellent.
I’m so tired of people who can’t hack it at C++ complaining about it. If real languages are too difficult, then scurry back to VB. As Rayiner and AKH point out, there are simple ways around this problem that you should be using; and as Nice points out, sometimes you want odd behaviors. C++ takes the position of NOT MAKING DECISIONS FOR YOU. Sometimes that means a little extra code, but in many cases it gives you flexibility to do things other languages just can’t handle. Just look at the amazing work being done at boost.org and ask yourself if you could do that kind of thing to any other language without changing the runtime support.
PS to Python fanboys: no, whitespace-sensitive languages are not cool. See fortran, ca. 1950.
Python rocks!!!, there is nothing wrong with white space sensitive languages as long as the language is powerful and has enough structures in the language to get a lot of the basic jobs done.
BTW…I also like and use C++ so I am not fanboy….. call me an anti-language-hater.
C++ tends to work very well when you have a tight group of experienced C++ developers that share a similiar style of programming. There’s probably not a mainstream language that offers the execution speed coupled with execution speed when used in that case. C++ development can start to break down when you have marginal players in the group and people aren’t adhering to a shared design/coding philosophy. Of course these problem are common with other languages too, but tend to be exaserbated with C++.
Unfortunately, productivity in C++ is often inversely proportional to execution speed. If you write proper STL code, you’ll be doing copies all over the place. Reference counting smart pointers are a lot slower than GC. That’s what really annoys me about modern C++. Its a great language totally hampered by backwards compatibility. If you ditched the C memory model (can directly access the bytes of structures) you could allow the compiler to do a whole lot more optimizations. Many of the template contortions the STL goes through would be completely unnecessary.
Does the complexity of C++ is absolutely needed to acheive its performance ? Does the metaprogramming support of C++ ( turing complete templates ) is a sensible metaprogramming language ?
I am still dreaming that a language can be both powerful and simple ( at least not awfully complex ).
For me, the main problem with C++ is the C compatability. C is a great, simple ( compiler side ), homogenic, coherent language. The C++ team didn’t want to break the compatibility ( also with the C preprocessor ), thus making C++ a mess.
The argument “real men use C++, keep playing with VB if you are not clever enough”, is childish. C is sometime called the only universal assembly language, C++ is still too descriptive, it may be a good target language for an higher level langage compiler ( that metacompiler can thus decide on the pointer allocation schemes, instead of letting the programming tweak the memory allocation and copying of every other data structure ! ).
C++ is a complex language but it is not particularly powerful, in the sense that you still have to tell to the computer every smallest detail.
That would be FORTRAN circa 1957-1990. Yes, at the time FORTRAN had what is now considered a goofy, column-based formatting for all programs.
However, its not so goofy when you realize the format is a holdover from having to write code that is then translated onto mechanical punchcards for input and output from your computer. That was the simple facts of computing life at the time. It was an elegant upgrade from directly inputing code in machine language using toggle switches.
Also, it has little to do with Python’s use of whitespace, which I enjoy as a means to highlight relevant blocks of code. I really wish I could use whitespace blocking as an option in other programs to help catch errors in the code, even if its not strictly enforced. Maybe this is possible in some form of optional preprocessor or code formatting application.
And for the record, modern Fortran arrays are very powerful and elegant. They simply work
Does the complexity of C++ is absolutely needed to acheive its performance ?
Not really. C++ will probably achieve better best-case performance, but I’ve seen Dylan’s containers achieve similar performance in the average case, and Dylan’s container API is a whole lot simpler.
Does the metaprogramming support of C++ ( turing complete templates ) is a sensible metaprogramming language ?
Not in the least. Its extremely limited, because it can’t do arbitrary code insertion. There are tons of languages with much better metaprogramming facilities.
I am still dreaming that a language can be both powerful and simple ( at least not awfully complex ).
Well, there are lots of languages that are both powerful and simple, and many are quite fast too. Depending on your tastes, you might like Ocaml, SML, Common Lisp, Scheme, Dylan, Smalltalk, Clean, or a number of others. The performance of good implementations of most of these languages is pretty good, with the best ones being closer to C++ than to Java.
The STL is value-oriented, not reference oriented. It encourages storing value types in its containers. Storing references in STL containers is a PITA, for several reasons:
1) You can’t use regular pointers, because the container wouldn’t free its contents when it went out of scope.
2) You can’t use references, because STL containers require the contained object to have a default constructor (and references require a parameter to an existing object during construction).
3) So you end up having to use a reference-counted smart pointer.
4) However, because of the pointer semantics of iterators, if the contained type is a reference, you end up basically using pointers to pointers, and have to dereference two levels of pointers when trying to get to the contained object. So you end up writing code that looks like (angle brackets replaced with parens):
Blech! And don’t give me “use should use type-defs.” There is something fundementally wrong wih a system that requires you to clutter your code with unnecessary type aliases just to write a for-loop easily. And I’d use for_each() instead, if only C++ had lambda!
Does the complexity of C++ is absolutely needed to acheive its performance ?
C++ has a number of features which are often only useful to programmers in very specific circumstances. However, in these circumstances these programmers will be very happy to have these features.
Does the metaprogramming support of C++ ( turing complete templates ) is a sensible metaprogramming language ?
I don’t know if C++ templates are necessarily “sensible”, but they are extremely useful. As an example of the “specific circumstances” above, say you are attempting to implement an FFT which will produce a fixed number of Fourier coefficients from a fixed length waveform input. With C++ templates, you can *easily* implement trigonometric functions as partial Taylor series expansions, and using that implement the entire FFT as a single mathematical expression, without loops or function calls. This will not only let the compiler optimize away redundant portions of the expression, which would be impossible with the use of loops/function calls (unless you had a runtime much smarter than the JVM or the .NET CLR), but the Taylor series expansions will often be optimized by the compiler to a single machine instruction.
Because of this, C++ allows unheard levels of code optimization by the compiler while the code still remains managable and intuitive by the programmer. I know of no other language which allows this (specific example).
The C++ team didn’t want to break the compatibility ( also with the C preprocessor ), thus making C++ a mess.
While ANSI C preprocessor syntax is somewhat limited (variable argument macroes would’ve been quite handy, gotta wait for C99), it’s quite necessary if you are targeting multiple platforms, specifically if you’re attempting to support multiple platform-specific interfaces which provide the same functionality. While the preprocessor is easily abused and difficult to use elegantly, it’s an extremely useful feature and one not easily parted with for those capable of using it properly.
Because of this, C++ allows unheard levels of code optimization by the compiler while the code still remains managable and intuitive by the programmer. I know of no other language which allows this (specific example).
Your Taylor series example could be done as a Common Lisp macro. And instead of using a very limited pseudo-functional language (the C++ template language) to do it, you’d get to use reguler code.
Macros take code optimization way further then you can get with C++. CL’s compiler-macro functionality lets you extend the compiler’s optimizer, to optimize domain-specific code that the compiler could not otherwise do itself.
Indeed, C++ optimizers are relatively primitive. There are all sorts of important analysis techniques they cannot use because of the C memory model. Templates give you some of the power of macros in the realm of optimization, but they’re a pale imitation.
To be efficient, one should use pointers in most cases with the stl.
This is what I was talking about. The STL containers are annoying to use with pointers. Hence my statement that if you want the productivity improvements of the STL, you’ll give up efficiency, namely invoke lots of copying.
The downside is that the pointers needed to be cleaned up before the object goes out of scope. I don’t think smart pointers can remedy this problem.
Yes they can. The smart pointer itself is a value object. When the container is deleted, the smart pointer’s destructor will be called. The destructor will decrement the reference count, and delete the object when the count hits zero.
>>The downside is that the pointers needed to be cleaned up >>before the object goes out of scope. I don’t think smart >>pointers can remedy this problem.
>Yes they can. The smart pointer itself is a value object. >When the container is deleted, the smart pointer’s destructor >will be called. The destructor will decrement the reference >count, and delete the object when the count hits zero.
Right on…. my mistake.
I’m thinking if I would really want to use smart pointers everywhere though. Certainly I wouldn’t use them in mathematical programming. I would prefer modularizing code in classes (rather than functions) which handle cleanup properly.
> C++ is a complex language but it is not particularly
> powerful, in the sense that you still have to tell
> to the computer every smallest detail.
What’s your con is my pro – I can use C++ to write device drivers, because the language allows me to tell the computer every smallest detail.
If you want higher-level structures, use the STL. If you want yet higher-leveled structures, use a library suited for your needs (like Boost smart pointers, for example). That’s the idea of C++ – being the swiss army knife among the languages – and to those who actually know their way around beginner’s mistakes, it delivers.
@ Rayiner:
> Hence my statement that if you want the productivity
> improvements of the STL, you’ll give up efficiency,
> namely invoke lots of copying.
Depends on what you want to do with your container. Perhaps you’re using the wrong container for what you have to do? Or perhaps you’d be better off still with a custom data structure customized to your needs?
From what I’ve read here, I know you are a qualified hacker, and I don’t mean this as an offense to your person, but rather a general hint for “effective C++”: Don’t try to make one structure (e.g., vector<>) fit everything. I’ve seen Java coders do this, and they created some of the ugliest, worst-performing code you’ve ever seen…
@ i_code_too_much:
> I’m thinking if I would really want to use smart
> pointers everywhere though.
That’s why you wouldn’t. Use whatever part of the language suits the task at hand. That’s why I usually prefer C++ over some more-suited-but-esoteric language: C++ is *wide*, it allows you to do many very different things (like, low-level bit hacking, C arrays, C++ vectors, smart pointers, garbage collection, highly custom container classes) and still remain within *one* language. I’d probably suck at writing Java, or Lisp, or {…}, but because I applied C++ to so many different problems I can move all the way up and down the scale.
Sorry for the rant. It’s just my favourite language… 😉
And use reference-counting smart pointers. Slightly different semantics (shared vs copies) but you usually want that anyway.
“reference-counting smart pointers”?
you mean smart pointers that only allocate on write?
Even Listing 2 is not correct. In the assignment operator, if new fails, this will leave “a” pointing to deleted storage. And the performance is not optimal, because in the assignment operator and the copy constructor objects will be default initialized, just to overwrite them in the next step. Instead, uninitialized storage should be allocated and then initialized with their final state. The standard library has the nice uninitialized_fill algorithm for that purpose…
with C++?
sure, there are some folks out there that have not learned it, but most folks in collage today have to take a C++ course.
C++ is a great source obfuscation tool. Needing to write custom constructors and copy operator for things as basic as arrays is awful. Does it really makes sense ?
feeding the troll..
in this example, the idea that you can assign the contents of a pointer when assigning a pointer are causing the ‘novice’ imagined by the article problems.
However, there might be equally occasions when assigning the pointer – and not creating a copy of the contents – is precisely what you meant to do.
I am not convinced that this article is strong on the usefulness factor (to myself), but I am sure that C++ is and remains a very very useful tool.
Of course, one would never actually write an array class like the one given in the example. Intead, you’d just use the STL vector. For static arrays you can use the boost array class, and for multidimensional arrays the boost multidimensional array class is excellent.
I’m so tired of people who can’t hack it at C++ complaining about it. If real languages are too difficult, then scurry back to VB. As Rayiner and AKH point out, there are simple ways around this problem that you should be using; and as Nice points out, sometimes you want odd behaviors. C++ takes the position of NOT MAKING DECISIONS FOR YOU. Sometimes that means a little extra code, but in many cases it gives you flexibility to do things other languages just can’t handle. Just look at the amazing work being done at boost.org and ask yourself if you could do that kind of thing to any other language without changing the runtime support.
PS to Python fanboys: no, whitespace-sensitive languages are not cool. See fortran, ca. 1950.
Python rocks!!!, there is nothing wrong with white space sensitive languages as long as the language is powerful and has enough structures in the language to get a lot of the basic jobs done.
BTW…I also like and use C++ so I am not fanboy….. call me an anti-language-hater.
C++ tends to work very well when you have a tight group of experienced C++ developers that share a similiar style of programming. There’s probably not a mainstream language that offers the execution speed coupled with execution speed when used in that case. C++ development can start to break down when you have marginal players in the group and people aren’t adhering to a shared design/coding philosophy. Of course these problem are common with other languages too, but tend to be exaserbated with C++.
ugh
s/execution speed coupled with execution speed/execution speed coupled with productivity/
Unfortunately, productivity in C++ is often inversely proportional to execution speed. If you write proper STL code, you’ll be doing copies all over the place. Reference counting smart pointers are a lot slower than GC. That’s what really annoys me about modern C++. Its a great language totally hampered by backwards compatibility. If you ditched the C memory model (can directly access the bytes of structures) you could allow the compiler to do a whole lot more optimizations. Many of the template contortions the STL goes through would be completely unnecessary.
Does the complexity of C++ is absolutely needed to acheive its performance ? Does the metaprogramming support of C++ ( turing complete templates ) is a sensible metaprogramming language ?
I am still dreaming that a language can be both powerful and simple ( at least not awfully complex ).
For me, the main problem with C++ is the C compatability. C is a great, simple ( compiler side ), homogenic, coherent language. The C++ team didn’t want to break the compatibility ( also with the C preprocessor ), thus making C++ a mess.
The argument “real men use C++, keep playing with VB if you are not clever enough”, is childish. C is sometime called the only universal assembly language, C++ is still too descriptive, it may be a good target language for an higher level langage compiler ( that metacompiler can thus decide on the pointer allocation schemes, instead of letting the programming tweak the memory allocation and copying of every other data structure ! ).
C++ is a complex language but it is not particularly powerful, in the sense that you still have to tell to the computer every smallest detail.
That would be FORTRAN circa 1957-1990. Yes, at the time FORTRAN had what is now considered a goofy, column-based formatting for all programs.
However, its not so goofy when you realize the format is a holdover from having to write code that is then translated onto mechanical punchcards for input and output from your computer. That was the simple facts of computing life at the time. It was an elegant upgrade from directly inputing code in machine language using toggle switches.
Also, it has little to do with Python’s use of whitespace, which I enjoy as a means to highlight relevant blocks of code. I really wish I could use whitespace blocking as an option in other programs to help catch errors in the code, even if its not strictly enforced. Maybe this is possible in some form of optional preprocessor or code formatting application.
And for the record, modern Fortran arrays are very powerful and elegant. They simply work
You gotta be shitting me. This made OSnews? What’s next? An article on for loops?
How embarassingly remedial.
Does the complexity of C++ is absolutely needed to acheive its performance ?
Not really. C++ will probably achieve better best-case performance, but I’ve seen Dylan’s containers achieve similar performance in the average case, and Dylan’s container API is a whole lot simpler.
Does the metaprogramming support of C++ ( turing complete templates ) is a sensible metaprogramming language ?
Not in the least. Its extremely limited, because it can’t do arbitrary code insertion. There are tons of languages with much better metaprogramming facilities.
I am still dreaming that a language can be both powerful and simple ( at least not awfully complex ).
Well, there are lots of languages that are both powerful and simple, and many are quite fast too. Depending on your tastes, you might like Ocaml, SML, Common Lisp, Scheme, Dylan, Smalltalk, Clean, or a number of others. The performance of good implementations of most of these languages is pretty good, with the best ones being closer to C++ than to Java.
>
> If you write proper STL code, you’ll be doing copies all >over the place. Reference counting smart pointers are a lot >slower than GC.
Could you further explain what you mean here? Proper STL/C++ code would use references instead of copies.
http://www.hitmill.com/programming/cpp/forLoop.htm
Here you go. Hope that will help you keep up with your classes.
The STL is value-oriented, not reference oriented. It encourages storing value types in its containers. Storing references in STL containers is a PITA, for several reasons:
1) You can’t use regular pointers, because the container wouldn’t free its contents when it went out of scope.
2) You can’t use references, because STL containers require the contained object to have a default constructor (and references require a parameter to an existing object during construction).
3) So you end up having to use a reference-counted smart pointer.
4) However, because of the pointer semantics of iterators, if the contained type is a reference, you end up basically using pointers to pointers, and have to dereference two levels of pointers when trying to get to the contained object. So you end up writing code that looks like (angle brackets replaced with parens):
std::map(std::string, boost::shared_ptr(contained_type))::iterator itr;
for(itr = container.begin(); itr != container.end(); ++itr)
(*itr)->call_function();
Blech! And don’t give me “use should use type-defs.” There is something fundementally wrong wih a system that requires you to clutter your code with unnecessary type aliases just to write a for-loop easily. And I’d use for_each() instead, if only C++ had lambda!
Does the complexity of C++ is absolutely needed to acheive its performance ?
C++ has a number of features which are often only useful to programmers in very specific circumstances. However, in these circumstances these programmers will be very happy to have these features.
Does the metaprogramming support of C++ ( turing complete templates ) is a sensible metaprogramming language ?
I don’t know if C++ templates are necessarily “sensible”, but they are extremely useful. As an example of the “specific circumstances” above, say you are attempting to implement an FFT which will produce a fixed number of Fourier coefficients from a fixed length waveform input. With C++ templates, you can *easily* implement trigonometric functions as partial Taylor series expansions, and using that implement the entire FFT as a single mathematical expression, without loops or function calls. This will not only let the compiler optimize away redundant portions of the expression, which would be impossible with the use of loops/function calls (unless you had a runtime much smarter than the JVM or the .NET CLR), but the Taylor series expansions will often be optimized by the compiler to a single machine instruction.
Because of this, C++ allows unheard levels of code optimization by the compiler while the code still remains managable and intuitive by the programmer. I know of no other language which allows this (specific example).
The C++ team didn’t want to break the compatibility ( also with the C preprocessor ), thus making C++ a mess.
While ANSI C preprocessor syntax is somewhat limited (variable argument macroes would’ve been quite handy, gotta wait for C99), it’s quite necessary if you are targeting multiple platforms, specifically if you’re attempting to support multiple platform-specific interfaces which provide the same functionality. While the preprocessor is easily abused and difficult to use elegantly, it’s an extremely useful feature and one not easily parted with for those capable of using it properly.
If only I had #if 0 in Java…
Now it’s clear what you were referring to.
To be efficient, one should use pointers in most cases with the stl.
The downside is that the pointers needed to be cleaned up before the object
goes out of scope. I don’t think smart pointers can remedy this problem. The
programmer still needs to do:
std::list(std::string*)::iterator itr;
for(itr = container.begin(); itr != container.end(); ++itr)
delete (*itr);
For a smart pointer, the delete will just decrease the reference count
unless the count becomes zero, in which case the memory would be freed.
One remedy is to write classes instead of functions for everything, make all
variables private in the class, and then have the destructor cleanup everything
when the object goes out of scope.
That is, instead of writing for example
void get_user_input(std::list<string*>& input) {
…
}
, one could write
class UserInput {
std::list<string*> input;
public:
virtual ~UserInput() { // cleanup pointers }
std::list<string*>& get_input();
};
That’s not the point.
Arrays in C++ are called ‘vector’ and are easy to use.
Because of this, C++ allows unheard levels of code optimization by the compiler while the code still remains managable and intuitive by the programmer. I know of no other language which allows this (specific example).
Your Taylor series example could be done as a Common Lisp macro. And instead of using a very limited pseudo-functional language (the C++ template language) to do it, you’d get to use reguler code.
Macros take code optimization way further then you can get with C++. CL’s compiler-macro functionality lets you extend the compiler’s optimizer, to optimize domain-specific code that the compiler could not otherwise do itself.
Indeed, C++ optimizers are relatively primitive. There are all sorts of important analysis techniques they cannot use because of the C memory model. Templates give you some of the power of macros in the realm of optimization, but they’re a pale imitation.
To be efficient, one should use pointers in most cases with the stl.
This is what I was talking about. The STL containers are annoying to use with pointers. Hence my statement that if you want the productivity improvements of the STL, you’ll give up efficiency, namely invoke lots of copying.
The downside is that the pointers needed to be cleaned up before the object goes out of scope. I don’t think smart pointers can remedy this problem.
Yes they can. The smart pointer itself is a value object. When the container is deleted, the smart pointer’s destructor will be called. The destructor will decrement the reference count, and delete the object when the count hits zero.
>>The downside is that the pointers needed to be cleaned up >>before the object goes out of scope. I don’t think smart >>pointers can remedy this problem.
>Yes they can. The smart pointer itself is a value object. >When the container is deleted, the smart pointer’s destructor >will be called. The destructor will decrement the reference >count, and delete the object when the count hits zero.
Right on…. my mistake.
I’m thinking if I would really want to use smart pointers everywhere though. Certainly I wouldn’t use them in mathematical programming. I would prefer modularizing code in classes (rather than functions) which handle cleanup properly.
@ Treza:
> C++ is a complex language but it is not particularly
> powerful, in the sense that you still have to tell
> to the computer every smallest detail.
What’s your con is my pro – I can use C++ to write device drivers, because the language allows me to tell the computer every smallest detail.
If you want higher-level structures, use the STL. If you want yet higher-leveled structures, use a library suited for your needs (like Boost smart pointers, for example). That’s the idea of C++ – being the swiss army knife among the languages – and to those who actually know their way around beginner’s mistakes, it delivers.
@ Rayiner:
> Hence my statement that if you want the productivity
> improvements of the STL, you’ll give up efficiency,
> namely invoke lots of copying.
Depends on what you want to do with your container. Perhaps you’re using the wrong container for what you have to do? Or perhaps you’d be better off still with a custom data structure customized to your needs?
From what I’ve read here, I know you are a qualified hacker, and I don’t mean this as an offense to your person, but rather a general hint for “effective C++”: Don’t try to make one structure (e.g., vector<>) fit everything. I’ve seen Java coders do this, and they created some of the ugliest, worst-performing code you’ve ever seen…
@ i_code_too_much:
> I’m thinking if I would really want to use smart
> pointers everywhere though.
That’s why you wouldn’t. Use whatever part of the language suits the task at hand. That’s why I usually prefer C++ over some more-suited-but-esoteric language: C++ is *wide*, it allows you to do many very different things (like, low-level bit hacking, C arrays, C++ vectors, smart pointers, garbage collection, highly custom container classes) and still remain within *one* language. I’d probably suck at writing Java, or Lisp, or {…}, but because I applied C++ to so many different problems I can move all the way up and down the scale.
Sorry for the rant. It’s just my favourite language… 😉