Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 字符串和常量char*和.c_str()?_C++_String - Fatal编程技术网

C++ 字符串和常量char*和.c_str()?

C++ 字符串和常量char*和.c_str()?,c++,string,C++,String,我遇到了一个奇怪的问题,我想知道为什么它会这样。我有一个类,其中有一个返回std::string的成员函数。我的目标是将这个字符串转换为const char*,因此我做了以下工作 const char* c; c = robot.pose_Str().c_str(); // is this safe?????? udp_slave.sendData(c); const char* c; std::string data(robot.pose_Str()

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

    const char* c;
    c = robot.pose_Str().c_str();  // is this safe??????
    udp_slave.sendData(c);
    const char* c;
    std::string data(robot.pose_Str());
    c = data.c_str();
    udp_slave.sendData(c);
问题是我在主人一方有一个奇怪的角色。但是,如果我做以下事情

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

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

这是一个指向临时方法的问题。 如果按值返回,但不存储
字符串
,它将在下一个序列点(分号)消失

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

考虑以下几点:

int f() { return 2; }


int*p = &f();
现在这看起来很傻,不是吗?您指向的是从
f
复制回来的值。你不知道它能活多久

您的
字符串的方式相同。

Q

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
中存储一个地址,该地址将是超出定义
s
c
范围的有效单位。

.c_str()
按值返回
char const*
的地址,这意味着它获取指针的副本。但在此之后,它所指向的实际字符数组将被销毁。这就是为什么你会收到垃圾。在后一种情况下,通过从实际位置复制字符,使用该字符数组创建一个新字符串。在这种情况下,虽然实际的字符数组已销毁,但副本仍保留在字符串对象中。

您不能使用
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.
}
#包括
#包括
#包括
std::string foo(){返回“hello”;}
煤焦*
复制(常量字符*s){
std::size_t sz=std::strlen(s);
char*p=新字符[sz];
标准:strcpy(p,s);
返回p;
}
int
main(){
const char*p1=foo().c_str();//哎呀,不能在此语句之后使用p1。
const char*p2=make_copy(foo().c_str());//可以,但完成后必须删除[]。
}
来自:

从c_str()获取的指针可能因以下原因而无效:

  • 将字符串的非常量引用传递给任何标准库函数,或
  • 对字符串调用非常量成员函数,不包括运算符[]、at()、front()、back()、begin()、rbegin()、end()和 rend()
这意味着,如果
robot.pose_Str()
返回的字符串被任何非常量函数破坏或更改,则指向该字符串的指针将无效。由于您可能会从
robot.pose_Str()
将临时副本返回到,因此在该调用之后,返回的
c_Str()
将立即无效

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

  • 如果您的函数
    udp\u send
    是同步的,请确保它能够工作
  • 或者依赖无效指针,因此如果
    udp\u send
    可能在对原始字符串的内部内容进行一些可能的修改后完成,则会遇到未定义的行为

我猜
pose\u Str()
返回字符串的副本。当pose_Str()返回时,将释放临时对象。所以C变成了一个野生指针。@比尔兹,我认为这是第一个答案。谢谢。只是说这不安全。我们不能仅仅通过这一行代码来判断它是否安全。如果
robot.pose_Str()
正在返回对
robot
的成员字符串字段的引用,并且如果
robot
的生命周期长于
c
,则它是安全的。