1

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) 更一般地说,按值返回对象容器是否会泄漏内存?(假设对象本身不泄漏)

4

5 回答 5

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

忘了效率,这段代码是不正确的。它不会正确读取文件。请参阅以下主题以了解原因

所以循环应该写成:

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

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


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

不。

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

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

于 2012-08-30T19:59:36.177 回答
1

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

我赞同 Nawaz 所说的,你的 while 循环是错误的。坦率地说,令人难以置信的是,我们看到了多少次,那里肯定有很多糟糕的建议。

于 2012-08-30T20:03:03.863 回答
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一个元素以删除最后一个空字符串。

于 2012-08-30T20:05:59.767 回答
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
}
于 2012-08-30T20:16:16.440 回答
0

不,按值返回容器不应泄漏内存。标准库被设计成在任何情况下都不会泄漏内存。如果其实现中存在错误,它只能泄漏内存。至少在旧的 MSVC中,字符串向量中曾经存在一个错误。

于 2012-08-30T20:07:45.980 回答