我是 C++ 编程新手(主要使用 Java),C++ 类、成员字符串和字符串转换为 const char*
的这种行为与 c_str()
让我很困惑。
我有一个 header 、一个类和主要函数,如下所示:
样本.h
class Sample
{
private:
int id;
std::string text;
public:
Sample(int id);
void setId(int id);
int getId();
void setText(std::string txt);
std::string getText();
void loadText();
~Sample();
}
示例.cpp
Sample::Sample(int id)
{
this->id = id;
}
void Sample::setId(int id)
{
this->id = id;
}
int Sample::getId()
{
return this->id;
}
void Sample::setText(std::string txt)
{
this->text = txt;
}
std::string Sample::getText()
{
return this->text;
}
void Sample::loadText()
{
this->text = "Loaded";
}
Sample::~Sample()
{
std::cout << "Destructor is called." << std::endl;
}
main.cpp
void main()
{
int id = 1;
Sample* sample = new Sample(id);
// Case: 1 - If I do this, it does not work. Prints gibberish.
sample->loadText();
const char* text = sample->getText().c_str();
std::cout << text << std::endl;
// Case: 2 - Otherwise, this works.
sample->loadText();
std::cout << sample->getText().c_str() << std::endl;
// Case: 3 - Or, this works
sample->loadText();
std::string txtCpy = sample->getText();
const char* text = textCpy.c_str();
std::cout << text << std::endl;
}
所有三种情况一次完成一个。
案例 3 确实满足我的用例(即将字符串传递给需要 const char*
的 C 库。但是,我无法弄清楚 Case: 1 和 Case: 3 之间的区别?如果我们是按值返回字符串,如何将其复制到中间变量使其适合运行时?
最佳答案
c_str()
的结果仅当您调用它的字符串仍然存在时才有效。在案例 3 中,txtCpy
在您撰写时仍然存在cout << text
。但在情况 1 中,该字符串是 sample->getText
的返回值。这是临时的,并在该行末尾停止存在。
如果您使用指向其他对象的指针或引用,则此问题始终存在。裸指针或引用有其自己的生命周期,该生命周期可能与目标对象的生命周期不同。这与 Java 不同,在 Java 中,对象引用都参与对象的生命周期。
因此,在使用这些功能时,您始终需要考虑对象的生命周期,并且通常建议使用更高级别的功能或其他不允许生命周期管理错误的代码样式。
您可以考虑向 Sample 添加一个成员函数,该函数获取 const char *
指向原始字符串(尽管这是对封装的轻微违反,并且如果您保留指针然后修改底层字符串,仍然存在类似的问题)。更好的办法是完全避免使用裸指针。
关于c++ - C++ 字符串返回和 c_str() 转换的令人困惑的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60555228/