-1

I have been following this tutorial and I can't understand this section.

So it says that pass by value creates copy of the data so that can be ineffiecient, since it creates copy of the data, makes sense:

string concatenate (string a, string b)
{
  return a+b;
}

then you have this, to 'solve the creating copies of data' issue:

string concatenate (string& a, string& b)
{
  return a+b;
}

which makes sense since it is using references.

But I do not get this:

string concatenate (const string& a, const string& b)
{
  return a+b;
}

Which says:

By qualifying them as const, the function is forbidden to modify the values of neither a nor b, but can actually access their values as references (aliases of the arguments), without having to make actual copies of the strings.

Why just not use the second way? In this example no modification of data is being done anyway? Can somebody give me a better example ?

Is it just done for safety reasons?

Rakete1111
  • 47,013
  • 16
  • 123
  • 162
Trt Trt
  • 5,330
  • 13
  • 53
  • 86
  • Try doing `concatenate(string("Hello"), string(" world"));` with the second version. – DeiDei Sep 10 '16 at 18:34
  • The example of @DeiDei is a good answer. Besides the guarantee of no modification, it allows passing temporary values. –  Sep 10 '16 at 18:39

4 Answers4

3

If the strings you actually have are const, or you only have const references to them, then you can pass them to this function:

string concatenate (const string& a, const string& b);

But you cannot pass them to this function:

string concatenate (string& a, string& b);

If your strings aren't const, then you can pass them to either function anyway. So other than ensuring that you don't modify the strings unintentionally, the const on the parameter allows for a more versatile function, which can accept either const or non-const arguments.

For example:

string concatenate_non_const (string& a, string& b)
{
    return a+b;
}

string concatenate_const (const string& a, const string& b)
{
    return a+b;
}

int main()
{
    std::string s1 = "hello";
    std::string s2 = "world";
    const std::string cs1 = "hello";
    const std::string cs2 = "world";

    concatenate_const(s1, s2);       // okay
    concatenate_const(cs1, cs2);     // okay

    concatenate_non_const(s1, s2);   // okay
    concatenate_non_const(cs1, cs2); // error
}

Also, besides objects which are declared const, there is also temporaries to think about, which cannot be bound to non-const references.

concatenate_const("hello", "world");     // okay
concatenate_non_const("hello", "world"); // error
Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
1

Why just not use the second way ? In this example no modification of data is being done anyway? Can somebody give me a better example ?

In your case here, where you are writing the function, It really doesn't matter, since you yourself aren't changing the parameters.

A better Example

A better example for using references over const references is for example with a swap function. Take this for example, which swaps 2 ints.

void swap(int& a, int& b)
{
    int temp = a;
    a = b;
    b = temp;
}

Now, in the example above, you cannot use a const reference, since the assignment to a and b would qualify as modification. In a function like above, references are very useful, and the const alternative would not work.

A less Concrete Example

Here is a less concrete example, that illustrates the same concepts as the swap(a,b) function:

void pre_incr(int& a)
{
    ++a;
}

Now the reason why this function is less concrete than the swap() one is that, you could have equally used pass by value like this:

void pre_incr(int a)
{
    return ++a;
}

Either way though, both functions illustrate the difference between pass by const reference and pass by normal reference, and also pass by value.

  • But in my question, what is the performance gain by using "const" ? Copies are not being created anyway, like you said no changes. When I just use references isn't the performance the same ? (in my example) – Trt Trt Sep 10 '16 at 18:37
  • The compiler can optimize and not allow modification of the parameter, and this would allow the compiler to throw an error, to say, if `a` or `b`, the strings you had are modified. –  Sep 10 '16 at 18:38
0

Is it just done for safety reasons ?

Much of what constitutes a programming language are "safety reasons", otherwise we could be jumping around labels in assembly like code.

Making the parameters of your function references to const strings serves two purposes:

  • You cannot accidentally modify the referenced strings.
  • It clearly documents "the strings you pass here will not be modified" to both other programmes (or your future self) and the compiler (and optimizer).

Consider this scenario:

string a = "foo", b = "bar";
cout << concatenate(a, b); // "foobar"

You get what you expect, even if you'd modified the passed strings in your concatenation function.

string a = "foo", b = "bar";
cout << concatenate(a, b);
// some code
string c = "baz";
cout << concatenate(a, c); // "Aaaabaz"

You'd probably search all of that "some code" to find modifications to a before even considering to look into concatenate ...

Also note that the first example (single use of the parameter strings) is what you'd likely find in a unit test for concatenate.

Daniel Jour
  • 15,896
  • 2
  • 36
  • 63
-1

When you pass a string in the first method with no const and no & it needs to be copied into the function which is inefficient. When you pass a reference it is not copied. When you pass by const reference it avoids the inefficiency of copying while not allowing the function to modify the string.

chasep255
  • 11,745
  • 8
  • 58
  • 115