Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I return const objects?

Tags:

c++

In Effective C++ Item 03, Use const whenever possible.

class Bigint {   int _data[MAXLEN];   //... public:   int& operator[](const int index) { return _data[index]; }   const int operator[](const int index) const { return _data[index]; }   //... }; 

const int operator[] does make difference from int& operator[].

But what about:

int foo() { } 

and

const int foo() { } 

Seems like that they're the same.

My question is, why we use const int operator[](const int index) const instead of int operator[](const int index) const ?

like image 793
abcdabcd987 Avatar asked Aug 21 '12 08:08

abcdabcd987


People also ask

When should I return my const?

Thus, it's important to use const when returning an object by value if you want to prevent its use as an lvalue. The reason const has no meaning when you're returning a built-in type by value is that the compiler already prevents it from being an lvalue (because it's always a value, and not a variable).

How do I return a const reference?

You want to return a const reference when you return a property of an object, that you want not to be modified out-side of it. For example: when your object has a name, you can make following method const std::string& get_name(){ return name; }; . Which is most optimal way.

What are const objects?

The const member functions are the functions which are declared as constant in the program. The object called by these functions cannot be modified. It is recommended to use const keyword so that accidental changes to object are avoided. A const member function can be called by any type of object.

What happens if you try to change a const?

Changing Value of a const variable through pointerThe compiler will give warning while typecasting and will discard the const qualifier. Compiler optimization is different for variables and pointers.


2 Answers

Top level cv-qualifiers on return types of non class type are ignored. Which means that even if you write:

int const foo(); 

The return type is int. If the return type is a reference, of course, the const is no longer top level, and the distinction between:

int& operator[]( int index ); 

and

int const& operator[]( int index ) const; 

is significant. (Note too that in function declarations, like the above, any top level cv-qualifiers are also ignored.)

The distinction is also relevant for return values of class type: if you return T const, then the caller cannot call non-const functions on the returned value, e.g.:

class Test { public:     void f();     void g() const; };  Test ff(); Test const gg();  ff().f();             //  legal ff().g();             //  legal gg().f();             //  **illegal** gg().g();             //  legal 
like image 195
James Kanze Avatar answered Oct 13 '22 23:10

James Kanze


You should clearly distinguish between the const usage applying to return values, parameters and the function itself.

Return values

  • If the function returns by value, the const doesn't matter, as the copy of the object is being returned. It will however matter in C++11 with move-semantics involved.
  • It also never does matter for basic types, as they are always copied.

Consider const std::string SomeMethod() const. It won't allow the (std::string&&) function to be used, as it expects non-const rvalue. In other words, the returned string will always be copied.

  • If the function returns by reference, const protects the returned object from being modified.

Parameters

  • If you pass a parameter by value, the const prevents the modification of given value by function in function. The original data from parameter can't be modified anyway, as you only have copy.
  • Note that since the copy is always created, the const has only meaning for function body, thus, it's checked only in function definition, not in declaration(interface).
  • If you pass a parameter by reference, the same rule as in return values applies

Function itself

  • If the function has const at the end, it can only run other const functions, and can't modify or allow modification of class data. Thus, if it returns by reference, the reference returned must be const. Only const functions can be called on object or reference to object which is const itself. Also the mutable fields can be changed.
  • The behavior created by the compiler changes this reference to T const*. The function can always const_cast this, but of course this shouldn't be done and is considered unsafe.
  • It's of course sensible to only use this specifier on class methods; global functions with const at the end will raise compilation error.

Conclusion

If your method doesn't and never will modify the class variables, mark it as const and be sure to meet all the critieria needed. It will allow more cleaner code to be written, thus keeping it const-correct. However, putting const everywhere without giving it any thought certainly isn't the way to go.

like image 30
Bartek Banachewicz Avatar answered Oct 14 '22 01:10

Bartek Banachewicz