Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Thinking in C++
Prev Contents / Index Next

Returning by const value

A similar truth holds for the return value. If you say that a function’s return value is const:

const int g();

you are promising that the original variable (inside the function frame) will not be modified. And again, because you’re returning it by value, it’s copied so the original value could never be modified via the return value.

At first, this can make the specification of const seem meaningless. You can see the apparent lack of effect of returning consts by value in this example:

//: C08:Constval.cpp
// Returning consts by value
// has no meaning for built-in types

int f3() { return 1; }
const int f4() { return 1; }

int main() {
  const int j = f3(); // Works fine
  int k = f4(); // But this works fine too!
} ///:~

For built-in types, it doesn’t matter whether you return by value as a const, so you should avoid confusing the client programmer and leave off the const when returning a built-in type by value.

Returning by value as a const becomes important when you’re dealing with user-defined types. If a function returns a class object by value as a const, the return value of that function cannot be an lvalue (that is, it cannot be assigned to or otherwise modified). For example:

//: C08:ConstReturnValues.cpp
// Constant return by value
// Result cannot be used as an lvalue

class X {
  int i;
public:
  X(int ii = 0);
  void modify();
};

X::X(int ii) { i = ii; }

void X::modify() { i++; }

X f5() {
  return X();
}

const X f6() {
  return X();
}

void f7(X& x) { // Pass by non-const reference
  x.modify();
}

int main() {
  f5() = X(1); // OK -- non-const return value
  f5().modify(); // OK
//!  f7(f5()); // Causes warning or error
// Causes compile-time errors:
//!  f7(f5());
//!  f6() = X(1);
//!  f6().modify();
//!  f7(f6());
} ///:~

f5( ) returns a non-const X object, while f6( ) returns a const X object. Only the non-const return value can be used as an lvalue. 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). Only when you’re returning objects of user-defined types by value does it become an issue.

The function f7( ) takes its argument as a non-const reference (an additional way of handling addresses in C++ and the subject of Chapter 11). This is effectively the same as taking a non-const pointer; it’s just that the syntax is different. The reason this won’t compile in C++ is because of the creation of a temporary.

Thinking in C++
Prev Contents / Index Next

 
 
   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire