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
Answertopia.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

Passing and returning addresses

If you pass or return an address (either a pointer or a reference), it’s possible for the client programmer to take it and modify the original value. If you make the pointer or reference a const, you prevent this from happening, which may save you some grief. In fact, whenever you’re passing an address into a function, you should make it a const if at all possible. If you don’t, you’re excluding the possibility of using that function with anything that is a const.

The choice of whether to return a pointer or reference to a const depends on what you want to allow your client programmer to do with it. Here’s an example that demonstrates the use of const pointers as function arguments and return values:

//: C08:ConstPointer.cpp
// Constant pointer arg/return

void t(int*) {}

void u(const int* cip) {
//!  *cip = 2; // Illegal -- modifies value
  int i = *cip; // OK -- copies value
//!  int* ip2 = cip; // Illegal: non-const
}

const char* v() {
  // Returns address of static character array:
  return "result of function v()";
}

const int* const w() {
  static int i;
  return &i;
}

int main() {
  int x = 0;
  int* ip = &x;
  const int* cip = &x;
  t(ip);  // OK
//!  t(cip); // Not OK
  u(ip);  // OK
  u(cip); // Also OK
//!  char* cp = v(); // Not OK
  const char* ccp = v(); // OK
//!  int* ip2 = w(); // Not OK
  const int* const ccip = w(); // OK
  const int* cip2 = w(); // OK
//!  *w() = 1; // Not OK
} ///:~

The function t( ) takes an ordinary non-const pointer as an argument, and u( ) takes a const pointer. Inside u( ) you can see that attempting to modify the destination of the const pointer is illegal, but you can of course copy the information out into a non-const variable. The compiler also prevents you from creating a non-const pointer using the address stored inside a const pointer.

The functions v( ) and w( ) test return value semantics. v( ) returns a const char* that is created from a character array literal. This statement actually produces the address of the character array literal, after the compiler creates it and stores it in the static storage area. As mentioned earlier, this character array is technically a constant, which is properly expressed by the return value of v( ).

The return value of w( ) requires that both the pointer and what it points to must be const. As with v( ), the value returned by w( ) is valid after the function returns only because it is static. You never want to return pointers to local stack variables because they will be invalid after the function returns and the stack is cleaned up. (Another common pointer you might return is the address of storage allocated on the heap, which is still valid after the function returns.)

In main( ), the functions are tested with various arguments. You can see that t( ) will accept a non-const pointer argument, but if you try to pass it a pointer to a const, there’s no promise that t( ) will leave the pointer’s destination alone, so the compiler gives you an error message. u( ) takes a const pointer, so it will accept both types of arguments. Thus, a function that takes a const pointer is more general than one that does not.

As expected, the return value of v( ) can be assigned only to a pointer to a const. You would also expect that the compiler refuses to assign the return value of w( ) to a non-const pointer, and accepts a const int* const, but it might be a bit surprising to see that it also accepts a const int*, which is not an exact match to the return type. Once again, because the value (which is the address contained in the pointer) is being copied, the promise that the original variable is untouched is automatically kept. Thus, the second const in const int* const is only meaningful when you try to use it as an lvalue, in which case the compiler prevents you.

Thinking in C++
Prev Contents / Index Next

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