`std::string::substr`, возвращающий неверный указатель?

Я пишу функцию для разделения C++ string на две отдельные stringс, в зависимости от местоположения конкретного персонажа. Однако, когда я использую указатели, которые он возвращает, они кажутся недействительными. Вот пример:

#include <iostream>
#include <string>

bool SplitString(std::string &input, char splitChar, std::string **left, std::string **right)
{
    std::string::size_type offset = input.find(splitChar);
    if (offset == std::string::npos) return false;
    *left = &input.substr(0, offset);
    *right = &input.substr(offset + 1);
    return true;
}

int main(int argc, char *argv[])
{
    std::string input = "Left side:Right side";
    std::string *left;
    std::string *right;

    if (SplitString(input, ':', &left, &right)) {
        std::cout << "left = \"" << *left << "\"" << std::endl;
        std::cout << "right = \"" << *right << "\"" << std::endl;
    } else {
        std::cout << "Didn't find ':' - this shouldn't happen!" << std::endl;
    }

    return 0;
}

Это должно вывести следующее:

left = "Left side"
right = "Right side"

Почему это не работает?

2 ответа

Решение

Вам не нужны указатели здесь. Ты можешь взять left а также right по ссылке. Возможно, вам не нужно принимать input по ссылке (вы не изменяете его, и если вы это сделали, что если вам придется выполнять другие манипуляции с тем же входом?) Так что либо передайте его по значению (если вы собираетесь работать с копией), либо const& (чтобы обозначить намерение не изменять его).

bool SplitString(std::string input, char splitChar, std::string& left, std::string& right)
{
    std::string::size_type offset = input.find(splitChar);
    if (offset == std::string::npos) return false;
    left = input.substr(0, offset);
    right = input.substr(offset + 1);
    return true;
}

// ...

    std::string left;
    std::string right;

    if (SplitString(input, ':', left, right)) {

// ...

Оказывается, когда я скомпилировал свой тестовый код с g++, он дал мне предупреждение, что компилятор Visual C++ не дал мне. Проблема в том, что объект возвращается std::string::substr считается "временным" и недействительным при использовании вне функции. Решение было, а не *left = &input.substr(0, offset), использовать *left = new std::string(input.substr(0, offset)), Очевидно, изменить *right линия аналогичным образом.

Не забудь delete новые объекты, когда вы закончите с ними!

Вот рабочий код:

#include <iostream>
#include <string>

bool SplitString(std::string &input, char splitChar, std::string **left, std::string **right)
{
    std::string::size_type offset = input.find(splitChar);
    if (offset == std::string::npos) return false;
    *left = new std::string(input.substr(0, offset));
    *right = new std::string(input.substr(offset + 1));
    return true;
}

int main(int argc, char *argv[])
{
    std::string input = "Left side:Right side";
    std::string *left;
    std::string *right;

    if (SplitString(input, ':', &left, &right)) {
        std::cout << "left = \"" << *left << "\"" << std::endl;
        std::cout << "right = \"" << *right << "\"" << std::endl;
    } else {
        std::cout << "Didn't find ':' - this shouldn't happen!" << std::endl;
    }

    delete left;
    delete right;
    return 0;
}
Другие вопросы по тегам