2014-10-20 48 views
-3

我正在写一个函数,根据特定字符的位置将C++ string分成两个独立的string。但是,当我使用它返回的指针时,它们似乎是无效的。这里有一个例子:`std :: string :: substr`返回无效指针?

#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" 

为什么不工作?

+3

为什么不直接发送对这些函数的字符串引用?为什么所有的指针都疯了? – PaulMcKenzie 2014-10-20 01:31:20

+0

这就是你得到一个右值的地址。 – 2014-10-20 01:31:25

+0

stdd :: string :: substr不返回一个std :: string *,它返回一个std :: string。你得到一个返回值的地址,当你调用你的第二个std :: string :: substr时,它将被覆盖。只需复制字符串。摆脱所有这些指针,并使用std :: string。 – Ben 2014-10-20 01:44:46

回答

3

你并不需要在这里指针。您可以参考leftright。可以说,你不需要参考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)) { 

// ... 
+0

为什么选择按价值输入作为默认值? – 2014-10-20 01:46:35

+0

'std :: string :: substr'方法构造一个新的字符串作为结果,当退出该函数时它将被销毁,因此,我们会在退出函数之前复制结果。顺便说一句,“输入”参数也可以作为参考。 – 2014-10-20 01:56:05

-6

原来,当我编译我的测试代码g++时,它给了我一个Visual C++编译器不给我的警告。问题是由std::string::substr返回的对象被认为是“临时的”,并且在函数之外使用时无效。解决方案是使用*left = new std::string(input.substr(0, offset))而不是*left = &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; 
} 
+0

当然,这只是暂时的;你从未将它分配给任何东西。 'substr'返回一个字符串。你取回了那个返回值的地址并丢弃了它自己的值。那么为什么在这个世界上,你会为此增加一个字符串?只需参考并分配'substr'的​​结果。让'string'完成它的工作并为你处理内存分配。另一方面,有更好的方法来分割一个字符串。使用'std :: getline'。 – 2014-10-20 01:23:57

+0

请解释一下这段代码的作用:'删除左边,右边;' – PaulMcKenzie 2014-10-20 01:30:26

+3

请注意''删除左边,右边''不会同时删除两个指针 – 2014-10-20 01:30:35