3

I would like to use the string splitting function for the highest rated answer to this question:

Split a string in C++?

Copying the answer for convenience:

#include <string>
#include <sstream>
#include <vector>

std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}


std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    split(s, delim, elems);
    return elems;
}

I have a question here. Why the declaration is std::vector<std::string> &split(...) rather than void split(...)? As an argument we receive std::vector<std::string> &elems and this is what we want to end up having. Why return anything if we receive a reference?

I have:

int &multA (int &n)
{
    n = 5*n;
    return n;
}

void multB (int &n)
{
    n = 5*n;
}

and:

int n1, n2;
n1 = 1;
n2 = 1;
cout << "n1: " << n1 << endl;
cout << "n2: " << n2 << endl;
n1 = multA(n1);
multB(n2);
cout << "n1: " << n1 << endl;
cout << "n2: " << n2 << endl;

And as a result I have:

n1: 1
n2: 1
n1: 5
n2: 5

What's the difference then?

Community
  • 1
  • 1

4 Answers4

5

Returning a reference allows a call to split() to be used as an argument to another function. For example, assume we have some other function that accepts a vector of strings by reference

  void func(std::vector<std::string> &elements);

If split() returns a reference, it is possible to pass the reference it returns directly to func().

  func(split(s, delim, elems));

whereas, if split() did not return a reference, it would be necessary to do

  split(s,delim, elems);
  func(elems);

The second usage approach still works if split() returns a reference.

The difference between these two is purely programmer convenience, but a lot of programmers prefer to use the first calling style. Returning a reference is not a particularly expensive operation so allowing the programmer a choice in how to use it does not lose much.

Peter
  • 35,646
  • 4
  • 32
  • 74
3

It's syntactic sugar that make the functions more flexible.

By example: you can write

std::cout << "there are " << split(str, delim, vect).size() << " elemements\n";

With the void hypothesis case, you need 2 statements.

max66
  • 65,235
  • 10
  • 71
  • 111
  • 1
    It would be more correct to use the word "statements" rather than "instructions". – Peter May 21 '16 at 14:45
  • @ Peter - thanks; I'm not native English speaker so often I fail using the correct terms (and maybe I'm wrong in my language too); I correct my answer. – max66 May 21 '16 at 15:04
  • 1
    No problem, but the english in your answer was (and is) fine. The word "statement" has a specific meaning in C++. The word "instruction" (in this context) has a particular meaning in computer science, which differs from a statement in C++. That sample of code you gave is a single C++ statement. – Peter May 21 '16 at 15:12
1

There is no difference in the examples you posted.

But there might be if you want to assign it to another variable and/or pass it to a function.

int a = multA(n1); //In one line :)
foo(multA(na1));   //Same thing, one line only

multB(n1);
int a = n1; //Two lines

multB(n1);
foo(n1);    //Two lines

Here multA is clearly better, because you can write it in one line, instead of 2 with multB. So basically the only difference.

Rakete1111
  • 47,013
  • 16
  • 123
  • 162
0

In term of result, there is no difference at all between these two methods.

However, option 1 makes it clear that the function multA has a computational result and that result is returned.

n1 = multA(n1);

On the other hand, the second option is not as self-explanatory as the first one. You cannot easily tell what multB is doing by reading the following code. It could be possible that multB is just logging a result with std::cout. But you cannot tell without reading the function definition.

multB(n2);
Yuchen
  • 30,852
  • 26
  • 164
  • 234