临时std :: strings返回垃圾

时间:2012-07-06 19:24:03

标签: c++

我还在学习c ++,所以请耐心等待。我正在编写一个关于boost文件系统路径的简单包装器 - 我在返回临时字符串方面遇到了奇怪的问题。这是我的简单类(这不是确切的,但非常接近):

typedef const char* CString;
typedef std::string String;
typedef boost::filesystem::path Path;

class FileReference {

    public:

        FileReference(const char* path) : mPath(path) {};

        // returns a path
        String  path() const {
            return mPath.string();
        };

        // returns a path a c string
        CString c_str() const {
            return mPath.string().c_str();
        };

    private:

        Path    mPath;

}

使用下面的小测试代码:

FileReference file("c:\\test.txt");

OutputDebugString(file.path().c_str()); // returns correctly c:\test.txt
OutputDebugString(file.c_str());        // returns junk (ie îþîþîþîþîþîþîþîþîþîþî.....)

我很确定这必须处理临时工,但我无法弄清楚为什么会这样 - 不应该一切都正确复制吗?

3 个答案:

答案 0 :(得分:8)

CString c_str() const {
        return mPath.string().c_str();
    };

mPath.string()会返回std::string的副本。该副本存储在临时表中,该副本将在此表达式的末尾被销毁。

.c_str()返回一个指向内存的指针,当字符串被销毁时,即在该表达式的末尾,它将被销毁。

您正在返回一个指向已经被破坏的内存的指针。

答案 1 :(得分:4)

看起来mPath.string()按值返回字符串。一旦FileReference :: c_str()返回,该临时字符串对象就被破坏,因此其c_str()变为无效。使用这样的模型,如果不为字符串引入某种类或静态级变量,则无法创建c_str()函数。

考虑以下备选方案:

//Returns a string by value (not a pointer!)
//Don't call it c_str() - that'd be misleading
String str() const
{             
     return mPath.string();
} 

void str(String &s) const
{             
     s = mPath.string();
} 

答案 2 :(得分:0)

表达式

OutputDebugString(file.path().c_str())

OutputDebugString(file.c_str())

类似,因为它们都在临时c_str()对象上有效地调用std::string方法并尝试使用该调用的结果。第一个将其直接称为file.path().c_str()子表达式。第二个更隐式地做到了:在FileReference::c_str()方法内部。

在第一种情况下,std::string调用显式创建临时file.path()对象作为整个表达式的直接部分。根据语言规则,该临时对象的生命周期延伸到整个表达式的末尾,这就是c_str()调用的临时和结果始终有效的原因。

在第二种情况下,在std::string方法中创建临时FileReference::c_str()对象。当此方法返回时,该临时对象将被销毁,这意味着FileReference::c_str()返回指向“死”数据的指针。这就是所谓“垃圾”的原因。