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)更普遍的是可以通过值返回容器的容器泄漏内存? (假设物体本身不泄漏)
答案 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。