47 comments

[ 3.6 ms ] story [ 112 ms ] thread
const type* const has always been a warning flag to me when I read it in other people's code. What are the advantages of making the pointer itself const?
I find it the opposite, when I read code that doesn't use const at all. In that case you want to make sure that code doesn't change either the value the pointer is pointing to and where the pointer is pointing to :)

<pre>

#include <stdio.h> void function ( int const * const value ) { printf ("%d\n", * value); / * more code * / ( * value)++; / * more code * / ++value; }

int main(int argc, char * * argv) { int value = 1; int * pvalue = &value; function(pvalue); return 0; }

$ gcc t1.c t1.c: In function ‘function’: t1.c:5: error: increment of read-only location ‘* value’ t1.c:7: error: increment of read-only location ‘value’ </pre>

quick googling: http://www.cprogramming.com/tutorial/const_correctness.html

EDIT: how can we properly paste code in here? The * mess things up.

Usually you take a look at the FAQ and read the http://news.ycombinator.com/formatdoc page.

  #include <stdio.h> 

  void function(int const * const value) 
  {
    printf ("%d\n", *value);
    
    /* more code */ 
    
    (*value)++;

    /* more code */

    ++value;
  }

  int main(int argc, char **argv)
  {
    int value = 1;
    int *pvalue = &value;

    function(pvalue);

    return 0;
  }

  $gcc t1.c 
  t1.c: In function ‘function’:
  t1.c:9: error: increment of read-only location
  t1.c:13: error: increment of read-only location
BTW: I agree, const is really useful

EDIT: I've recompiled on OSX to correct the error message with the correct lines.

I think you misunderstand. When I see, in a function like yours

  void function(int const * const value)
it worries me because it shows me that the writer doesn't know the meaning of const. There is no added value of this declaration over

  void function(int const *value)
or the more commonly seen

  void function(const int *value)
The only thing that has changed in your code is that the implementor of the function can't modify his own private copy of the pointer.
To ensure there are no side effects - at least to ensure that that object in question is not mutated. I think const refs are a little more useful than const pointers for this.
Do you find const actually catches bugs?

I admittedly don't use C++ that frequently, but if I make my code const-correct it always seems to cause a lot of false positives, while seldom finding actual bugs.

I disagree, especially const-correct methods help avoiding mutation. The primary mistake IMO is that const can be cast away. Invariant should be invariant (like D).
A lot of people seem to be horrified that you can cast constness away. Maybe they have more traumatic experiences than I do, but I believe that if something is possible to do (modifiying an object that is declared const), it should be possible in the language as well. That does not mean it should have well specified semantics or that it should be done without proper considerations.
const does not so much catch bugs as it prevents them. It is a way to specify a contract. If your code is const-correct, the next programmer using or maintaining your code can read a function or method signature and know immediately which parameters will not change, or whether the object will be modified. Effective C++ explains this very well, and I fell in love with const after reading its second edition almost 10 years ago.
That would be const type pointer. (HN apparently won't let me type more than one asterisk in the message without turning everything between them to italics.) const type pointer const is a const pointer to a const object, i.e. the pointer itself can't be mutated to point to a different object.

I've never found a need for it. I usually don't care if the pointer itself is modified, particularly since such modifications are usually local and obvious.

It is useful for static (possibly global) data which if const can be placed in the read-only data section. For local variables or function parameters it is less useful.
Perhaps the point is that C++ is heavy and if there are alternatives you should use them instead. Just because you invested years getting up to speed doesn't mean everyone else should do the same. I have to use C++ at work occasionally so I'll probably end up having a few years invested in getting to know C++ too. But at this stage the startup cost is considerable and very very present. If I had a choice I wouldn't consider it a good value.
In the standard C++ world, yes. However, if you use a rich class library, such as Qt, there is not all that much difference in difficulty compared to e.g. Java (even down to Java-style iterators).
I've been using C++ for the last 6 years. Recently I moved to the web group which uses ruby and seriously, I never want to code another line of C++ ever.

I dont feel that way about C though and its probably because of C++'s immense complexity. If everyone on your team has 7+ years of using C++ and most of its features on a day to day basis then I think you have a chance (however remote) of getting a clean maintainable system. If not you get a good ugly mess.

(And yes I've created a few myself, while learning this language :)

Do you really think this is a fair comparison? Web dev has never been C++'s strong point. I could as well say, "so, I've been using Haskell for desktop and console gaming. After 6 years, I moved to C++ and man, I never want to code a line of Haskell again." Because it's a completely inappropriate language choice.

Also re: maintainability. C++ is completely maintainable, and built from the ground up for maintainability specifically in large projects.

Don't blame C++ for the sins of Microsoft (managed C++ extensions, DLL HEll, C++ COM interfaces, compiler support classes, 9 different string types). Don't blame C++ for the sins of gcc. At some point we need to distinguish between the (pure) LANGUAGE and the (often politically motivated) TOOLSET.

I don't think actually that C++ as a language is a inappropriate for web dev, but it lacks the great frameworks that more popular choices have (RoR, Django etc).
Agreed. There is no really good web framework for C++. This is a weakness of C++ going forward. I suppose you could do ASP.NET or ASP.NET MVC with C++/CLI...though in that case it would seem C# or VB.NET is indicated...
I am not sure, a lot of convenience of modern web frameworks is made possible using introspection and other runtime facilities, which are too minimal in C++.
(comment deleted)
I'm not comparing C++ with ruby for webdev. I just said that I moved to a webdev job from a realtime trading job where we used c++. I'm just saying that my mental state of mind at work has become much better because of the change. I'm purely talking about language differences. One simple exaple is the difference in time it takes to code a snippet that iterates over an array of arrays. In c++ this would take me atleast 15 minutes (finding all the types involved, compiles for error checking etc) with no test written. In ruby I cud have everything done in 1 minute.

The better the tool you use the less stress it puts on you the builder.

Don't blame C++ for the sins of Microsoft

Most of those sins were committed specifically to address weaknesses in C++.

A language without a first-class late-binding model is fundamentally broken. Don't blame Microsoft for trying, however ineffectively, to fix it.

It depends on the task. For e.g. client-side applications, Ruby makes deployment painful, since everyone has their own versions of Ruby with different sets and versions of gems. Added to that, a lot of people are not allowed to install the necessary dependencies on work machines. And then, Windows has no such thing at all.

With C++ and Qt on the other hand, it's very easy to write self-contained applications, also with a minimum amount of platform-dependent code.

> It depends on the task. For e.g. client-side applications, Ruby makes deployment painful, since everyone has their own versions of Ruby with different sets and versions of gems. Added to that, a lot of people are not allowed to install the necessary dependencies on work machines. And then, Windows has no such thing at all.

This is quite easy to fix on linux. You compile a your required version of ruby beside the application that needs it.

    /srv/<application>
         src/
         ruby/ <-- install ruby here with the proper flags
         build-ruby.sh <--- custom script to download, build, and install ruby
I've done this as a matter of principle my own server. It allows me to swap out what ruby version I run my app on without messing with the ruby installed on the system.

The bundler project is also trying to the gem problem by bundling gems with your application.

So basically you think mastery of C++ is always 1 year away?
(comment deleted)
One man project with 25 KLOC? A bit limited example IMO. No problem with C++ strings if you don't use 'em. Well, that's a solution ...
boost has a nice threading library too. He didn't mention that when listing other portable threading alternatives and I think the boost implementation will be in the next standard.
Folks often poo-poo Apple's choice of Objective C, but I find that a VERY graceful object oriented extension of C, and far nicer than C++ or Java (yuck!).
I did GUI development in C++ for a number of years, and it really boggles the mind just how much more suitable Objective-C is for high-level application design than C++/COM, and without the overhead of a VM.

C++ has its place, but that place is getting smaller and smaller each day, making the advanced features of C++ all the more irrelevant.

(comment deleted)
I find this post to be a little bit like saying:

"Why running with one leg is great" - written by someone who run each days with one leg.

Of course, if you're using C++ each days of your life, you become quite good at it. You know the downside, you learn to use external libraries, etc. However, it's when you actually switch to another language that you can look behind realize all the time and effort you lost.

It's when you actually start running with 2 legs that you know for sure that, yes maybe one leg is ok, but 2 legs is easier, simpler, faster and safer.

Oh, some says it's better to use a car, well, I don't care because 2 legs is ok for me. [to be completed]

> Of course, if you're using C++ each days of your life, you become quite good at it. You know the downside, you learn to use external libraries, etc. However, it's when you actually switch to another language that you can look behind realize all the time and effort you lost.

I work on a real-time visualization application for microscopes. Main requirements:

1) Performance (DSP and image processing involved)

2) Decent GUI

3) Must be maintainable by students in engineering physics

What I am supposed to use that's easier, simpler, faster and safer than C++/Qt for this? Even dropping the "maintainable" thing, I don't see any language that would let me code faster. And my app doesn't have very unusual requirements...

The fact that you are forced to use C++ for all the reasons you said doesn't make it a better language. Again, to continue my comparison with legs:

If you lose one of your shoes and need to walk in the street, you might be better to jump with only one leg.. it doesn't make it better than 2 legs.

In the same way, if you needed raw performance, need to control your memory, etc. C++ might be the only way to go.

However, for your particular problem, I don't know if it's possible, but a mix of Python for GUI and C for the raw algorithm could have been easier.

And, for students in engineering physics, Python is way simpler than C++. From my experience, I helped students in other concentration than computer at university, and they had all kind of: #include <iostream.h>, lots of global variable named with only one letter, etc.. in their code.

But don't get me wrong, C++ has its use and I keep using it again and again for various project. I know however that when I can use other language such as python, I'm way more effective and the final code is really prettier and simpler.

Sadly, as in everything in life, nothing is black or white.. if C++ fits you well for a project, uses it. It's nobody's business anyway. I think it's important however to know that if you only use and know C++, you miss something.

(comment deleted)
> "Why running with one leg is great" - written by someone who run each days with one leg.

He is not saying that C++ is great. In fact he mentions several issues that bother him in his day to day use of the language. The problem with a lot of the anti-C++ rants is that they make it sound like it is impossible to get anything done in C++, which of course is not the case. Memory management for example is often brought up as a major issue with C++. I have been in 200+kloc projects that never leak memory and very, very rarely have to call delete. Just use RAII - it's not rocket science.

With c++ programs, there is a well-understood model for how memory works and decent tools/method for finding memory leaks.

A garbage collected program should never leak memory but if it does, then your problem is nastier - for example, how do you find memory leaks in C# in Mono? The tools are not sufficient. And standard Ruby, btw, doesn't official leak memory but simply never return allocated memory to the main pool - it keeps it in a private pool for future allocation. But allocate 1Gig and your Ruby instance will keep that 1Gig forever.

> when you actually switch to another language

When I'm using some scripting language and not Qt, I wish I was using Qt.

Qt is the shit. If you haven't used it you can't criticize C++. I've whipped up several things I know would have taken me ages longer to achieve the performance requirements with anything else.

What's wrong with C++ can ironically be summed up by how a C++ (or C) compiler would parse 'C++'. If the value of C++ were accessed at that line, a temporary would be generated to access the original C value, and then after the line C would be incremented.

The idea is that most other languages are ++C. or ++A. The operation isn't straddled across two lines. Backwards compatibility with another language (C) isn't so important. And all the language features aren't generated implicitly without a real clear idea about the design (i.e., via temporaries).

On the other hand, it is possible to program in something like ++C -- no temporaries -- by consciously going through and picking which features you like in C++, and not waiting for them to influence your design in some weird way (hence these types of posts about C++, and how different programmers have different takes on the language -- and different tools, moc, etc.). That is, if you want to write really elegant C++ code, you have to write it with a vengeance. It's not orthogonal really like Python or Ruby. It's much more like Perl. Just as the compiler is generating unnecessary cycles by creating that temporary (9/10), so are the C++ design paradigms often very overlapping and if you're not careful and don't understand them in detail -- they'll create a lot of unnecessary design cycles.

But I think with the right tools and the right focused perspective, it's still one of the best languages. It's not forgiving -- and sometimes it's almost misleading -- I mean from the very beginning, you'd think if you wanted simply to increment an integer or an object semantically you'd just foo++ -- but that'd usually be wrong.

But the redeeming part about C++ is that all languages make these mistakes. All languages, in trying to improve on their predecessors, make limiting choices that are imperfect and at some point will be optimized or revised in the future. The beauty, if you can call it that, of C++ -- is that because of its performance bent, it doesn't force you to choose any of its features which aren't already in C.

With regards to the const part of the discussion -

Does anyone knows any research or even a state of affairs of const inference in language design?

The idea is similar to type inference whereby a compiler (or some other tool in a chain) would take care of understanding which arguments/variables/functions are going to be const and generate appropriate warnings based on that. For example,

  void foo(int * a) { (*a)++; }

  void bar(int * b) { foo(b); }

  void baz(const int * c) { bar(c); }
A compiler would generate a warning when baz function, because foo() includes a non-const operation on its argument, bar() is non-const for the same reason, and so it cannot be called for a const pointer.
I'm not sure what you mean, since current compilers already warn if you write that code.
Hmm, OK. Try a different example - the compiler should allow the following code without any warnings:

  void foo(int * a) { }

  void bar(int * b) { foo(b); }

  void baz(const int * c) { bar(c); }
Point being is that the compiler should warn of the const violation based on whether a function argument or a class member is getting touched in the function code.

In fact, the example above is more relevant, because what I am ultimately aiming for is to not need to make member functions const, and yet be able to call them for const class instances.

I just put a similar response in another post, but its just as appropriate here...

If you want to know how C++ can be better, you should take a look at at the Reason C++ framwork, especially if you have never seen C++ in its most pure uncomplicated OO form.

http://reasoning.info

Reason is a C++ framework that ive been writing for about 8 years, which aleviates many of the sources of pain highlighted in this discussion. Writing code with Reason is much more like using a dynamic language, with a full library like Java or .Net.

It supports raii, but doesnt use exception handling and doesnt bother with const nonsense or over the top inheritance restrictions. In fact pretty much everything in Reason is public and designed to be derived, modified or enhanced.

It has generic programming features, but doesnt force you to write everything as templates (a classic mistake that the standard library makes). For example, you can have an iterator of int's without caring what the underlying container type is, so your code and algorithms can actually be generic, not just infectious templates.

Unlike a lot of C++ frameworks and libraries, its not specifically focused on networking, or a few esoteric template classes or collection libraries.

Reason is a fully featured systems programming framework with a complete interface to all the usual posix api's and everything else you would expect from a modern language. It has strings, regexes, streams, parsers, sockets, threads, filesystem, encryption, encoding, xml, xpath, collections, time and date, sql (mysql, postgress, sqlite), http (client/server), smart pointers, formatting, logging, and much more.

But the features are perhaps not as important as how it is written. It is simple, and very object oriented, everything is designed to work togeather cleanly and obey the principle of least surprise. Just like Python and Ruby, Reason allows you to do a lot in a very small amount of code.

So if your wondering how you can have the simplicity of C, with just the good parts of C++, heres your answer.

http://reasoning.info