string和const char *和.c_str()?

时间:2014-05-05 03:51:36

标签: c++ string

我遇到了一个奇怪的问题,我想知道它为什么会这样。我有一个类,其中有一个返回std::string的成员函数。我的目标是将此string转换为const char*,因此我执行了以下操作

    const char* c;
    c = robot.pose_Str().c_str();  // is this safe??????
    udp_slave.sendData(c);

问题是我在Master方面得到了一个奇怪的角色。但是,如果我执行以下操作

    const char* c;
    std::string data(robot.pose_Str());
    c = data.c_str();
    udp_slave.sendData(c);

我得到了我期待的东西。我的问题是上述两种方法之间的区别是什么?

5 个答案:

答案 0 :(得分:20)

这是指向临时的问题。 如果按值返回但不存储string,则它会在下一个序列点(分号)消失。

如果将它存储在变量中,则指针指向udp发送期间实际存在的内容

请考虑以下事项:

int f() { return 2; }


int*p = &f();

现在看起来很傻,不是吗?您指向的是从f复制回来的值。你不知道它会活多久。

您的string也是一样。

答案 1 :(得分:6)

.c_str()按值返回char const*的地址,这意味着它获取指针的副本。但在那之后,它指向的实际字符数组将被销毁。这就是你得到垃圾的原因。在后一种情况下,您将通过从实际位置复制字符来创建具有该字符数组的新字符串。在这种情况下,虽然实际的字符数组被销毁,但副本仍保留在字符串对象中。

答案 2 :(得分:5)

c_str()对象的生命周期之后,您无法使用std::string指向的数据。有时它不清楚生命周期是什么,例如下面的代码。解决方案也显示出来了:

#include <string>
#include <cstddef>
#include <cstring>

std::string foo() { return "hello"; }

char *
make_copy(const char *s) {
    std::size_t sz = std::strlen(s);
    char *p = new char[sz];
    std::strcpy(p, s);
    return p;
}

int
main() {
    const char *p1 = foo().c_str(); // Whoops, can't use p1 after this statement.
    const char *p2 = make_copy(foo().c_str()); // Okay, but you have to delete [] when done.
}

答案 3 :(得分:5)

来自c_str()

  

从c_str()获得的指针可以通过以下方式无效:

     
      
  • 将对字符串的非const引用传递给任何标准库函数,或
  •   
  • 在字符串上调用非const成员函数,不包括operator [],at(),front(),back(),begin(),rbegin(),end()和   雷德()。
  •   

这意味着,如果robot.pose_Str()返回的字符串被任何非const函数销毁或更改,则指向该字符串的指针将无效。由于您可能会从robot.pose_Str()返回临时副本,因此c_str()之后的udp_send返回将在该呼叫之后无效。

然而,如果您返回对您可能持有的内部字符串的引用,而不是临时副本,您可以:

  • 确保它能够正常工作,以防你的函数udp_send同步;
  • 或依赖于无效指针,因此如果在对原始字符串的内部内容进行某些可能的修改后{{1}}可能完成,则会遇到未定义的行为。

答案 4 :(得分:3)

const char* c;
c = robot.pose_Str().c_str();  // is this safe??????
udp_slave.sendData(c);

<强> A

这可能不安全。这取决于robot.pose_Str()返回的内容。如果返回的std::string的生命周期长于c的生命周期,那么它是安全的。否则,它不是。

您正在c中存储一个在语句执行完毕后无效的地址。

std::string s = robot.pose_Str();
const char* c = s.c_str();  // This is safe
udp_slave.sendData(c);

在这里,您要在c中存储一个地址,该地址将是您从sc定义的范围之外的有效单位。