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