STL 容器和内存泄漏
STL containers & memory leaks
C#编码器刚刚编写了一个简单的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) 更普遍地说,按值返回对象的容器是否会泄漏内存?(假设对象本身没有泄漏)
while (theFile.good()) {
getline (theFile, line);
lines.push_back(line);
}
忘记效率吧,这段代码是不正确的。它将无法正确读取文件。请参阅以下主题了解为什么:
- 什么';从C++文件中读取行的首选模式是什么
所以循环应该写成:
while (getline (theFile, line)) {
lines.push_back(line);
}
现在这是正确的。如果您想提高效率,请先对您的应用程序进行配置文件。尝试查看占用大部分CPU周期的部分。
(1) 这个代码会泄露内存吗?
没有。
(2) 更普遍地说,按值返回对象的容器是否会泄漏内存?
取决于容器中对象的类型。在您的情况下,std::vector
中对象的类型是std::string
,这可以确保不会泄漏内存。
No和No。按值返回永远不会泄露内存(假设容器和包含的对象写得很好)。如果是其他方式,那将是相当无用的。
我支持纳瓦兹所说的,你的while循环是错误的。坦率地说,令人难以置信的是,我们看到了多少次,肯定有很多糟糕的建议。
(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
少一个元素以删除最后一个空字符串。
在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
}
否,按值返回容器不应泄漏内存。标准库的设计在任何情况下都不会泄漏内存。只有当它的实现中存在错误时,它才能泄漏内存。至少在一个旧的MSVC中,字符串向量曾经有一个错误。
- 从构造函数抛出异常时如何克服内存泄漏
- malloc() 可能出现内存泄漏
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 尽管遵循了规则,内存泄漏在哪里
- 为什么调用堆栈数组会导致内存泄漏
- 在简单示例中,Python3 + ctypes 回调会导致内存泄漏
- 使用模板类的自定义列表类型中的内存泄漏
- 为什么以下C++代码中存在内存泄漏?
- OpenCV 我应该使用智能指针来防止内存泄漏吗?
- 我是否生成线程并导致内存泄漏?
- 多线程程序中出现意外的内存泄漏
- 为什么此函数会导致内存泄漏?
- 在 C++ 库中使用cythonized python时内存泄漏
- 需要帮助查找内存泄漏
- 瓦尔格林德的内存泄漏使用新的
- 无法找出我的代码中的内存泄漏
- C++ 结构内部的unordered_map会导致内存泄漏问题吗?
- 可视化 使用 VS Code 查找C++应用程序中的内存泄漏
- Shared_ptr双链接列表内存泄漏
- C++ 在类中使用常量引用文本时 O2 内存泄漏