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
,则它是安全的。