0

What is the best strategy is for returning a modified copy of a string from a function? From my experience in programming in C, I know that it is generally preferable to return a pointer to a large object (array or struct) instead of a copy.

I have the following example, where I pass a string type to a C++ function and return a char *. I was wondering how I should go about returning a string object instead. If I were to return a string, would it be advisable to return a copy or dynamically allocate it and return the pointer?

#include <iostream>

using namespace std;

char *removeSpaces(string sentence)
{
    char *newSentence = new char[sentence.size()]; // At most as long as original
    int j = 0;
    for (int i = 0; i < sentence.size(); i++) {
        if (sentence[i] == ' ') {
            newSentence[j++] = ' ';
            while (sentence[++i] == ' ');
        }
        newSentence[j++] = sentence[i];
    }
    return newSentence;
}

int main(void)
{
    string sentence;
    cout << "Enter a sentence: ";
    getline(cin, sentence);
   
    char *sentenceSpacesRemoved = removeSpaces(sentence);
    cout << "After removing spaces: ";
    cout << sentenceSpacesRemoved << endl;

    delete[] sentenceSpacesRemoved;
    return 0;
}
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
First User
  • 704
  • 5
  • 12
  • 1
    In C++ you can just return a `std::string` by-value, and the compiler will use the "return value optimization" ( https://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization ) to avoid having to make a copy of the data. So you get the best of both worlds, code that is hard to get wrong and also optimal efficiency. – Jeremy Friesner Feb 09 '23 at 06:13
  • Return a std::array, if you can, or just modify a string passed as a reference. – user1095108 Feb 09 '23 at 06:13
  • `sentenceSpacesRemoved` is not a null terminated char array. `sentence[++i]` goes after sentence end if a space is at the end. – 273K Feb 09 '23 at 06:16
  • Why you are you using `new` at all, if you're allowed to use `string`? – HolyBlackCat Feb 09 '23 at 06:36

1 Answers1

3

Thanks to copy elision, you can just return a stack-allocated string object from a function without any overhead:

std::string getString()
{
    std::string str;
    return str;
}

Moreover, you can get "guaranteed" elision (since C++17) if you construct the string right in the return expression:

std::string getString()
{
    return std::string{};
}

If you don't need a copy at all, however, for your scenario you can just pass the string and remove whitespaces in-place:

void removeSpaces(std::string& sentence)
{
    for (auto it = std::cbegin(sentence); it != std::cend(sentence); ++it) {
        if (*it == ' ') {
            it = sentence.erase(it);
        }
    }
}
The Dreams Wind
  • 8,416
  • 2
  • 19
  • 49