Domanda

This question is inspired by a question about final in java.

In C/C++, should I use const whenever possible?

I know there is already a related question about using const in parameters. Unfortunately that question and it's answers don't fully answer my question, because it's only about function parameters, but I would also like to know about other cases (eg: local variables).

Also, almost all answers to that question say we should use const because it contains useful information about the accessibility of variables. But this seems to conflict with an answer about using final in Java which states final may be superfluous if it doesn't contain extra information and so it should be omitted to keep the code short and clean.

So, should I use const whenever possible? If so, why is the advice for const in C++ different from the advice for final in Java?

È stato utile?

Soluzione

First of all, since you referenced Java's final, that is a totally different beast than const. Final means the reference cannot change, but says nothing about mutability. Const goes further by saying "a const reference cannot mutate" which is a much stronger guarantee. To do this in Java, internal state must be final and determined at construction time. Const is a lot easier to use, and an existing object can be "promoted" into a const reference.

Yes, you should use const whenever possible. It makes a contract that your code will not change something. Remember, a non-const variable can be passed in to a function that accepts a const parameter. You can always add const, but not take it away (not without a const cast which is a really bad idea).

Const-correctness may be tedious at times, but it helps guarantee immutability. This is crucial in multi-threaded code where threads share objects. It makes certain tasks more efficient: instead of copying state, just reuse the same immutable object. Libraries might accept const parameters in order to provide a guarantee to the programmer that no, your object will not change in an unpredictable way in the black hole that is the library's guts.

Altri suggerimenti

Personally, const takes me very little time to write, and very little time to read, usually much less than it takes to check whether any code mutates the variable, and it actually prevents me from writing bugs (anyone ever incremented their end iterator by accident? Etc)

I also find that being strict about const usage guides me towards better code in other ways, like creating helper functions to do non-trivial initialization.

I'm going to disagree with the other posters and recommend you don't use top-level const on local variables and parameters. (References and pointers to const, i.e. const T&, are different, and you should use them for correctness at all times when it's appropriate.)

The advantages of top-level const are:

  • Makes it clear that the local variables are not meant to be mutated.
  • Gives a compiler error if you accidentally do attempt to mutate them.

The disadvantages are:

  • Visual clutter.
  • Cannot be used on "pseudo-const" variables, i.e. variables that are initialized in some manner more complicated than direct construction, but not modified after, e.g. using getline:

    std::string line; // cannot be const
    std::getline(std::cin, line);
    // line should be const from here on out
    
  • Prevents move-out optimization on function call and return:

    std::string f1();
    std::string f2(std::string s);
    std::string f3() {
      const std::string s = f1(); // s is not meant to be modified
      // but I still want the move optimization here:
      const std::string result = f2(std::move(s)); // this doesn't move
      // and I want the compiler to move out here:
      return result; // this will probably RVO, but if not, the move
                     // constructor will not be used due to the const
    }
    

I have worked on a codebase where local const was used a lot, and I found it not helpful at all, yet it filled the code with subtle pessimizations as above. I personally prefer to adopt a general policy of modifying variables as rarely as possible, and making functions small enough that the usage of a variable is obvious, and even if it is modified, the complexity of the function is low enough to make it a non-issue.

The const keyword should be used for local variables, just like parameters. It's useful because:

  • Easier to read the code. When someone reads the variable declaration, she knows it won't change. One less thing to worry while reading your code.
  • Prevent you accidentally modify the variable
  • No runtime penalty, everything is checked statically. It's like a free lunch, const should take just a second to write, so it's no big deal.
  • It's always a good idea to make your variables/parameters in your multi-threaded applications. Even your application is not multi-threaded, it's still a good habit.
  • You give an opportunity for your C++ compiler to optimize your code.

Note that there's no right/wrong answer here. In your link, the answerer who had the most upvotes argued final shouldn't be used locally. However, the next answerer strongly recommended it.

If your function is simple and trivial, you shouldn't add const because everyone understands your intention. However, if the logic in your function is non-trivial, you should use the keyword. Remember, there is little to lose.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
scroll top