Подтвердить что ты не робот

Еще один момент обучения С++: возвращение строк из функций

У меня есть некоторые основные вопросы о С++. Рассмотрим следующий код, в котором я пытаюсь вернуть строку.

const std::string&
NumberHolder::getValueString() {
    char valueCharArray[100];
    sprintf_s(valueCharArray,"%f",_value);
    std::string valueString(valueCharArray);
    return valueString;
}

Я пытаюсь вернуть строку со значением члена класса с именем _value. Однако я получаю предупреждение о том, что я пытаюсь передать указатель на локальную переменную. Это, конечно, плохо. Если я понимаю С++ достаточно на этом этапе, это означает, что указатель, который я передаю, уже будет иметь удаление, вызванное им, к тому времени, когда кто-то попытается его использовать. Поэтому я изменяю:

const std::string&
NumberHolder::getValueString() {
    char valueCharArray[100];
    sprintf_s(valueCharArray,"%f",_value);
    std::string valueString = new std::string(valueCharArray);
    return (*valueString);
}

Это должно создать указатель на стек, который выйдет за пределы этой функции. Две проблемы здесь: 1) он все равно не компилируется, и я не понимаю, почему (error = не может преобразовать из 'std::string *' в 'std:: basic_string < _Elem, _Traits, _Ax > ') и 2) Это похоже на потенциальную утечку памяти, потому что я зависим от кого-то другого, чтобы называть этого парня. Какую модель мне следует использовать здесь?

4b9b3361

Ответ 1

Вы побеждаете точку с std::string, выделив ее в куче!

Просто верните его по значению, как это:

std::string NumberHolder::getValueString()
{ 
    char valueCharArray[100]; 
    sprintf_s(valueCharArray,"%f",_value); 
    return std::string(valueCharArray); 
} 

Почти каждый компилятор теперь сделает оптимизацию возвращаемого значения (RVO) в инструкции return, поэтому никаких копий не следует делать. Рассмотрим следующее:

NumberHolder holder;
// ...
std::string returnedString = holder.getValueString();

С RVO компилятор будет генерировать код для вышеупомянутой реализации NumberHolder::getValueString(), так что std::string создается в месте returnedString, поэтому копии не нужны.

Ответ 2

Вы получаете это предупреждение, потому что вы возвращаете ссылку на локальную строку, а не копию локальной строки. Как только функция вернется, локальная строка будет уничтожена, а возвращаемая вами ссылка недействительна. Таким образом, вам нужно вернуть строку по значению, а не по ссылке:

std::string NumberHolder::getValueString()

Ответ 3

Ваша первая попытка правильная, если вы возвращаете временную переменную, но привязываете ее в константной ссылке.

const std::string NumberHolder::getValueString(){}

const std::string& val = NumberHolder::getValueString();

const. Но ваша вторая попытка опасна, в зависимости от кого-то еще, чтобы удалить.

Ответ 4

std::string *valueString = new std::string(valueCharArray);

Вам нужно будет создать переменную-указатель, чтобы сохранить результат из new, так как он возвращает указатель. Однако идеальным решением было бы просто вернуться по значению:

std::string NumberHolder::getValueString() {
    ...
    return std::string(valueCharArray);
}