4

I just stumbled over Evan Teran's answer on Split a string in C++?, in which he takes a vector by reference, modifies it and returns a reference of it.

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;
}

Is this good style? I see that the advantage is to directly use the result, like in

std::vector<std::string> vec;
unsigned int uiSize = split("ssad asda", ' ', vec).size();

instead of

std::vector<std::string> vec;
split("ssad asda", ' ', vec);
unsigned int uiSize = .size()

Are there any disadvantages? As far as I know, the main reason against returning references is that people might return a reference of a local variable which is destructed after the return. This does not apply here, as the object is not local but given to the method as a parameter.

Community
  • 1
  • 1
Fabian
  • 4,001
  • 4
  • 28
  • 59
  • 3
    I see no problem for this use case for returning reference. it's like `operator<<` – Garf365 Mar 03 '16 at 09:01
  • 2
    This is a reasonable thing to do, for chaining commands. For instance, this approach is used for `operator<<` for printing. Still useful for function calls rather than operators. – BoBTFish Mar 03 '16 at 09:02

1 Answers1

2

The code

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;
}

is misleadingly named: it's more of an append_lines than split function.

But given that, it makes sense to return a reference to the vector, yes. Returning by value could not in general benefit from move semantics, and so would incur some needless overhead. And void result could make the calling code pretty clumsy & awkward.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331