首页 > 解决方案 > C++ 字符串返回和 c_str() 强制转换的令人困惑的行为

问题描述

我是 C++ 编程新手(主要使用 Java),C++ 类、成员字符串和字符串转换到const char*with的这种行为c_str()让我感到困惑。

我有一个标题,一个类和主要功能如下:

样本.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;
}

主文件

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;
}

所有三个案例一次完成一个。

Case 3 确实满足我的用例(即将字符串传递给需要 a 的 C 库const char*。但是,我无法弄清楚 Case: 1 和 Case: 3 之间的区别?如果我们按值返回字符串,将其复制到中间变量如何使其在运行时符合犹太教规?

标签: c++stringpointersmemoryc-strings

解决方案


的结果c_str()仅在您调用它的字符串仍然存在时才有效。在第 3 种情况下,txtCpy您正在编写的点仍然存在cout << text。但在案例 1 中,该字符串的返回值sample->getText是临时的,并且在该行的末尾停止存在。

如果您使用指向其他对象的指针或引用,此问题将始终存在。裸指针或引用有自己的生命周期,可能与目标对象的生命周期不同。这与 Java 中的对象引用都参与对象的生命周期不同。

因此,在使用这些功能时,您总是需要考虑对象的生命周期,通常建议改用更高级别的功能或其他不允许生命周期管理错误的代码样式。

您可以考虑向 Sample 添加一个成员函数,该函数const char *指向原始字符串(尽管这有点违反封装,如果您按住指针然后修改底层字符串,仍然存在类似的问题)。最好完全避免使用裸指针。


推荐阅读