Hacker News new | ask | show | jobs
by nickolai 5287 days ago
I don't understand his matrix example.

in C++, you'd have a Matrix class with a getter. To get an element of the matrix you'd do

  int v = pMatrix->get(i,j);
whereas in C you'd typedef a Matrix structure type and have an accessor function

  int v = matrix_get(pMatrix,i,j);
Looking inside the functions, they'do pretty much the same thing. In both of these functions you'd be basically accessing either element i+imax * j of your data array if you are implementing the matrix as a single array, or the j-th element of the i-th row if you were using a pointer to pointer structure. the C version would work on the provided matrix structire whereas the C++ would use the implicitly provided this structure. C++ would allow your matrix class to override some operator to make this look cooler - but operator overloading being a good thing is not really a consensus AFAIK.

I dont see anything more than a syntactic difference here. The abstract reasoning behind the structures/classes is exactly the same.

C may be obsolete, but this is hardly a justification.

3 comments

If you now wanted to have polymorphism, you'd have to do even more work in the function, which would probably involve looking up a function pointer in a table and invoking that (i.e. Linux VFS). If you didn't start out wanting polymorphism, but then wanted to add it, C++ is way less work to do it.

Why code this all by hand when the language can do it for you at no penalty? The only penalty I see in C++ for using classes or polymorphism is that it produces longer symbol names (w/ the type mangling)

You also get destructors that let you have convenient clean up of locally-allocated data (boost scoped_ptr), which helps make sure you don't leak memory/reduces bugs/reduced thinking required.

That's all possible without pulling out massive standard libraries or using slow-compiling/hard-to-diagnose template-based libraries (merits of those I leave undiscussed).

My biggest problem with C++ is a lack of a standard ABI (perhaps this has been addressed by know, it's been a while). C libraries are dead easy to link to. You know what you're getting. C++--not at all, unless you live entirely in the same compiler ecosystem.

One of the biggest perceived problems with C++ is that people start thinking: "well, now that I am using an OO language, it's time to write some classes!" Of course, just because you're using classes doesn't mean you're doing any useful object-oriented programming.

If you're attempting your next project in C++, coming from C: only use those features of C++ that directly benefit you. Follow YAGNI. If most of your program is in flat procedures, alongside some objects, so be it.

Side rant: Consider that C++'s real uptake was in mid-90's, just as UML-ish diagrams began taking hold along with a massive rise of overdesign and no culture of agility. This led to massively overdesigned C++ apps. I'm sure the C developers were sitting there and wondering "Why the hell do I need all these classes? This used to be so much simpler." (I know I was.) Think about the horror that was J2EE--the same kind of thinking that led to J2EE also permeated C++ development at the time.

Right now, you'd have to do a lot of convincing to get me to write native code in straight C again.

> Why code this all by hand when the language can do it for you at no penalty? The only penalty I see in C++ for using classes or polymorphism is that it produces longer symbol names (w/ the type mangling)

There are other penalties which people who write C++ are oblivious to. For example, switching the class of an established object in runtime:

Suppose you have two compatible class layouts (same field order and types, different methods). When you implement dispatch yourself, switching the behavior is a simple matter of replacing the vtbl pointer from one class to the other (I'm not sure Linux VFS does this, but it's common enough in C object systems).

Whereas if you use C++, the standard solution is to break this into a dataless "strategy" object (which can be changed independently of the data) and a data object which contains the state. If you never had the luxury of doing something like "if (obj->class == Living) obj->class = Zombie", you don't miss it, but it doesn't mean you're not missing out on some flexibility.

> Of course, just because you're using classes doesn't mean you're doing any useful object-oriented programming.

Furthermore, just because you are doing object-oriented programming doesn't mean it is useful. (And a purist would say, just because you are doing programming, doesn't meant it is useful)

> Right now, you'd have to do a lot of convincing to get me to write native code in straight C again.

I've switched to C++ in 1993 and back to C in 2004 when compile times with boost started to measure on a geological time scale and single error messages spilled onto my 2nd screen -- and haven't looked back. When a write GUIs, I do use FLTK which is C++ (very effective, but not idiomatic), because I haven't seen a GUI toolkit as good that's native C -- but other than that, I don't miss anything, and I'm not less productive.

C++, the language, has a lot of useful tools, but C++, the ecosystem, guarantees that in any nontrivial project you'll be thrown into the tarpit. In my experience, the overall effect of C++ on a project is negative. YMMV.

>In my experience, the overall effect of C++ on a project is negative. YMMV.

Curious: What's your domain?

In video games where there are a lot of "objects" floating around that can really benefit from polymorphism, the type checking that C++ can do that C can't really gives you a huge development bonus.

Of course I'm saying this having moved past C++ for 99% of the development into an elegant and tiny scripting language called Lua, where you can do just about anything (including having an object system that you can change an object from one type to another trivially if that's what you want).

> Curious: What's your domain?

I switch every couple of years. Most recently: Image analysis; previously: Big data analysis; Before that: financial mathematics ("quant") and trading systems. If I go back long enough to '91-95: Game programming (SNES and PC); although I've been somewhat involved in game programming and related projects as late as 2008.

> In video games where there are a lot of "objects" floating around that can really benefit from polymorphism, the type checking that C++ can do that C can't really gives you a huge development bonus.

Only if your logic is written in C++ as well. In the projects I was involved with, most of the logic was actually data driven or scripted, and C++ contributes much less in that scenario.

I don't deny C++ has its uses. But it also has a lot of drawbacks. Whether or not the net is gain or loss compared to $LANGUAGE, is subjective. For me with $LANGUAGE=C, it is negative. YMMV.

Hmm, a friend of mine from Criterion said that in two of the last games they did, they had to re-write the Lua parts (fairly significant) in C++ to get the framerate high enough as it's memory fragmentation was just too much.

They went from ~34 fps to ~60 fps for 4 developer weeks re-writing the Lua code.

Ask them if they were using LuaJIT2; they probably didn't -- it's relatively new (only been stable enough for real work for less than a year).

It is ludicrously fast. It usually loses to optimized C / C++, but by no more than 10-20% -- and you have essentially no restrictions whatsoever on the Lua features you use; Furthermore, it's FFI makes interoperating with C / C++ a superfast breeze, dropping the FFI overhead to zero.

And even ignoring LuaJIT2 -- they probably took less time and got higher quality overall by going through Lua (assuming programmers were equally versed in Lua and C++, and the infrastructure was reasonable) -- it's easier to iterate and debug with Lua than it is with C++.

LuaJIT2 is awesome, but it still uses the Lua 5.1.4 garbage collector, so if the problem was GC related (i.e., memory fragmentation), then LuaJIT2 wouldn't help much.

OTOH, changing how you do things in Lua CAN be a big help in not generating garbage. I love the ability to ignore memory allocation in Lua, and I'm annoyed that I have to deal with thinking about it, but at least it's pretty straightforward.

Also, depending on the game, you can nuke your Lua allocation every level/section/other segment, allocating Lua memory from a memory pool. That can also help a lot with fragmentation.

But if you're doing a game that's one continuous experience, you have no choice but to be careful with managing memory. Again, it CAN be done from within Lua (think object pools), and that could be easier than porting to C++. And with LuaJIT 2, it would likely be fast enough in that case.

You can of course implement the same functionality using either C or C++. I agree - the two implementations would be very similar. But I don't think this is the point Bjarne is trying to make.

C++ challenges you to think in terms of types instead of functions. This is in my opinion often a more natural way to approach and solve problems and thus produces more elegant code. Because of that, C++ is a very powerful tool for library developers - you can design libraries that allow domain-specific developers to write expressive code that performs as if you had written more verbose C code. And this C++ code is not only more expressive for your fellow co-workers to read and understand but also in some cases for the compiler. This is the reason why C++ code can sometimes be compiled to faster machine code: you can give the compiler more information about what you actually try to accomplish (keyword: template meta-programming).

As with most things there is no definite answer. C code can be quite elegant and appropriate as well.

I think the point he was trying to make is that a good language allows a library to be a "domain specific embedded language", in which an expert in some domain who is not an expert in the host language can do meaningful work. The matrix example is a particularly flattering one for C++, since a good matrix library in C++ will provide syntax that is quite close to the notation that one would use on paper for matrices.
The matrix example is a particularly flattering one for C++, since a good matrix library in C++ will provide syntax that is quite close to the notation that one would use on paper for matrices.

And it either (a) creates and destroys many intermediate structures or (b) templates everything by exposing the entire implementation to the user, resulting in slow compilation time and error messages that the domain expert couldn't hope to decipher.

It's almost as if everything has tradeoffs, and engineers have to make them consciously!

Optimize when necessary. Until then, no need to mutilate expressiveness if the language allows it.

Yeah, I'm not a big fan of C++, really. That said, (a) is mostly solved in 11 with rvalue references, isn't it?
I think the matrix example is particularly unflattering, and highlights the fundamental issues with the language. For once, there is no agreed-upon matrix library in C++, but many different ones. They are only "compatible" at a very low-level (a contiguous memory buffer), and the promises of performances often broken. The only one I know of that has been delivering on the performance front is eigen3, but I think the difficulty of the approach to become slightly ridiculous. When you need some "dynamic" optimization as done by eigen, C++ and templates are rather crude tools IMO.