STL容器&内存泄漏

时间:2012-08-30 19:56:02

标签: c++ stl

C#coder刚刚编写了这个简单的C ++方法来从文件中获取文本:

static std::vector<std::string> readTextFile(const std::string &filePath) {
    std::string line;
    std::vector<std::string> lines;
    std::ifstream theFile(filePath.c_str());
    while (theFile.good()) {
    getline (theFile, line);
        lines.push_back(line);
    }
    theFile.close();
    return lines;
}   

我知道这段代码效率不高;文本行在读取时复制一次,在按值返回时复制第二次。

两个问题:

(1)这段代码可以泄漏内存吗? (2)更普遍的是可以通过值返回容器的容器泄漏内存? (假设物体本身不泄漏)

5 个答案:

答案 0 :(得分:5)

while (theFile.good()) {
 getline (theFile, line);
    lines.push_back(line);
}

忘记效率,这段代码不正确。它无法正确读取文件。请参阅以下主题以了解 为什么

所以循环应该写成:

while (getline (theFile, line)) {
    lines.push_back(line);
}

现在这是正确的。如果您想提高效率,请首先分析您的应用程序。尝试查看占用大多数CPU周期的部分。


  

(1)这段代码可以泄漏内存吗?

没有

  

(2)更一般地说,按值返回容器的容器是否会泄漏内存?

取决于容器中对象的类型。在您的情况下,std::vector中对象的类型std::string,这样可确保不会泄露内存。

答案 1 :(得分:1)

不,不。按值返回永远不会泄漏内存(假设容器和包含的对象写得很好)。如果是其他任何方式,它将毫无用处。

我是Nawaz所说的,你的while循环是错误的。坦白地说,我们多少次看到这一点,那里肯定会有很多糟糕的建议。

答案 2 :(得分:1)

  

(1)这段代码可以泄漏内存吗?

没有

  

(2)更一般地说,按值返回容器的容器是否会泄漏内存?

没有。您可能会通过指针或泄漏的对象泄漏存储在容器中的内存。但这不是由按值返回引起的。

  

我知道这段代码效率不高;文本行在读取时复制一次,在按值返回时复制第二次。

很可能不是。字符串有两个副本,但不是您正在考虑的副本。返回副本很可能会在C ++ 03中进行优化,并且可以在C ++ 11中进行优化或转换为移动(便宜)。

两个应对是:

getline (theFile, line);
lines.push_back(line);

第一行从文件复制到line,第二行从line复制到容器。如果您使用的是C ++ 11编译器,则可以将第二行更改为:

lines.push_back(std::move(line));

字符串的内容移动到容器中。或者(也在C ++ 03中有效),您可以使用以下内容更改两行:

lines.push_back(std::string()); // In most implementations this is *cheap*
                                // (i.e. no memory allocation)
getline(theFile, lines.back());

你应该测试读取的结果(如果读取失败,在最后一个替代方案中,确保resize减去一个元素以删除最后一个空字符串。

答案 3 :(得分:1)

在C ++ 11中,你可以这样做:

std::vector<std::string> 
read_text_file(const std::string& path) 
{
    std::string line;
    std::vector<std::string> ans;
    std::ifstream file(path.c_str());

    while (std::getline(file, line))
       ans.push_back(std::move(line));

    return ans;
}

并且没有额外的副本。

在C ++ 03中,您接受了额外的副本,并且只有在分析指示时才会删除它们。

注意:您不需要手动关闭文件,std::ifstream的析构函数会为您完成。

注意2:您可以对char类型进行模板化,这在某些情况下可能很有用:

template <typename C, typename T>
std::vector<std::basic_string<C, T>>
read_text_file(const char* path)
{
    std::basic_string<C, T> line;
    std::vector<std::basic_string<C, T>> ans;
    std::basic_ifstream<C, T> file(path);

    // Rest as above
}

答案 4 :(得分:0)

不,按值返回容器不应泄漏内存。标准库的设计不会在任何情况下泄漏内存本身。如果其实现中存在错误,它只能泄漏内存。至少在旧的MSVC中曾经有bug in vector of strings

相关问题