Why is there a need for reference parameters in C++?

We’ve been learning about reference parameters in my Intro to Programming class. I understand perfectly that reference parameters give you access to the place where an argument is held in memory, while value parameters create copies of the arguments.

Why would I want my function to have access to the argument’s memory location instead of its value?

6

There are a few reasons this may be useful.

Non-copyable types

Not everything can be passed by value! std::unique_ptr, for example, may only be moved, not copied, because it makes no sense to copy something that has unique ownership over a resource. Its copy constructor has been “deleted”, which means passing it by value into any function will simply fail.

Large types

Maybe your function only needs to inspect the object’s current value, without actually changing it. If the object is large, copying it is pointless and wasteful. Not only are you taking up more memory and CPU cycles than you need, but if you have a deep recursion, yes you may indeed contribute to the likelihood of a stack overflow because your stack frames are much larger than they need to be.

Typically, in these scenarios, we’ll pass by const reference to avoid accidental mutations.

Mutation

Maybe the object is being passed in as an “out” parameter, so that the changes made inside the function are to be visible at the call site. Here’s an example:

bool foo(std::string& a)
{
    const char* result = someSysCall("...");
    if (result) {
       a = result;
       return true;
    }
    else {
       return false;
    }
}

int main()
{
    std::string str;
    if (foo(str)) {
       // do things with str
    }
    else {
       // show an error?
    }
}

While oftentimes we’d use exceptions instead of this pattern, out parameters are still widespread in many libraries (particularly the Windows API). They are often implemented using pointers instead, but the principle is exactly the same.

C gets by with having values and pointers. C++ adds references.

A lot of this is to support operator overloading. For example, let’s assume you want to overload operator -- or operator = for some particular type. Both of these (and quite a few more besides) need to modify the object they receive as a parameter.

Now, in C when you need to have a function modify something, you pass a pointer to that something. When you’re dealing with an overloaded operator, however, you don’t really have that option. If you have code like ++foo; or foo -= bar;, you don’t have any real way to specify that for this case, I want to pass the address of foo instead of its value. To pass the address, you need to take the address at the call site, so you end up with things like

scanf("%d", &destination);

References allow you to achieve roughly the same result, but the syntax to do so is entirely in the called function rather than at the call site, so a normal expression with normal syntax can still pass a reference so the called function can modify its parameter.

Although there certainly are other perfectly valid uses for references in C++, and using them can be (often is) cleaner and safe than using a pointer, most other cases could be done using a pointer if references weren’t available. This case pretty much requires a reference–it simply won’t work with a pointer.

5

Ah! Something just came to mind – recursion. If a recursive function needs access to a variable, and you want the function to pass that variable to itself, then you want – and may need – a reference parameter. Otherwise, you’re just allocating unnecessary memory – and may, in fact, cause a “stack overflow”.

Edit: Some people have noted that pointers exist. Be that as it may, reference variables are sometimes preferable simply because they render referencing and dereferencing unnecessary.

5

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *