Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the differences between parameter definitions as (type& name), and (type* name)?

A very basic question, but still, it would be good to hear from C++ gurus out there.

There are two rather similar ways to declare by-reference parameters in C++.

1) Using "asterisk":

void DoOne(std::wstring* iData);

2) Using "ampersand":

void DoTwo(std::wstring& iData);

What are implications of each method? Are there any gotcha's in any case?

Bonus #1: What would be a formal way to call method in #1 and #2? Are they both called "by-reference"?

Bonus #2: std::wstring is used deliberately. What would be implications towards standard library classes in each case?

like image 696
Ignas Limanauskas Avatar asked Jun 04 '09 06:06

Ignas Limanauskas


People also ask

What is parameter and types of parameter?

A parameter is a named variable passed into a function. Parameter variables are used to import arguments into functions. Note the difference between parameters and arguments: Function parameters are the names listed in the function's definition.

What is the difference between the types of parameters explained in Chapter 4 used in methods and the types of values that can be returned from a function?

What is the difference between the types of parameters (explained in Chapter 4) used in methods and the types of values that can be returned from a function? The parameters are passed in as input in methods whereas a function's value is obtained after running the function.


3 Answers

#1 uses a pointer parameter ('passing a pointer to'), #2 uses a reference parameter ('passing by reference'). They are very similar, but note that the calling code looks different in the two cases:

std::wstring s;

DoOne(&s); // pass a pointer to s
DoTwo(s); // pass s by reference

Some people prefer #1, using a convention that passing by pointer indicates that the function might change the value of s (even though either function could). Other people (myself included) prefer #2, since passing by reference does not allow NULL to be passed.

There is another important difference when passing by const pointer or reference. A temporary variable can only be passed to a const reference parameter:

void ByConstPointer(const std::wstring&);
void ByConstReference(const std::wstring*);

void test()
{
  ByConstPointer(&std::wstring(L"Hello")); // error: cannot take address of temporary
  ByConstReference(std::wstring(L"Hello")); // fine
}
like image 73
James Hopkin Avatar answered Nov 15 '22 07:11

James Hopkin


Rule number one for this: If NULL is a valid value for the function parameter in the context of the function, then pass it as pointer, otherwise pass it as reference.

Rationale, if it cannot (should not!) ever be NULL, then don't put yourself through the trouble of checking for NULL.

like image 42
Johann Gerell Avatar answered Nov 15 '22 06:11

Johann Gerell


While writing examples, I came up with my own answer. Anything other than below?

The result of each of them is quite similar: a reference to an object in the memory ends up within method's scope. There seem to be no strict memory requirements for any of them. The object can be either on stack or in heap.

In case of stack each of the methods would be called like this:

{
    std::wstring data;
    DoOne(&data);
    DoTwo(data);
}

Yet, when it comes to the heap, the second approach would require that the object must exist before calling the method. If the object does not exist, the caller would cause exception, not the callee.

{
    std::wstring* pData = new std::wstring();
    DoOne(pData);
    DoTwo(*pData);
}

In the above, if out-of-memory condition occurs and pData ends up NULL, the crash would happen before DoTwo, but DoOne would swallow the NULL and might crash some time later.

like image 37
Ignas Limanauskas Avatar answered Nov 15 '22 07:11

Ignas Limanauskas