我有以下功能模板:
template<typename T>
void init(std::vector<T>& v, int min, int max)
{
for(int i = min; i <= max; i++)
v.push_back(new T());
}
将使用另一个函数,如下所示:
void foo()
{
std::vector v;
init(v, 10, 20);
//something else
}
如果在函数T
中初始化init
类型的某个对象期间抛出某些异常会发生什么?
在这种情况下或某些其他类型的UB,我会得到内存泄漏吗?如果是这样,我该如何预防?
答案 0 :(得分:4)
如果内存分配失败,您将获得std::bad_alloc
异常。如果在执行类型T的构造期间存在异常,则应使用try catch块在类型T的构造函数中处理。
如果使用std::vector::push_back
运算符创建对象后new
失败,则存在内存泄漏的可能性,因为新生成的原始指针还不是向量的一部分。因为您正在创建一个原始向量使用new
运算符生成的指针,作为正确清理的一部分,您应该对向量的内容调用delete
。 std::vector<>
析构函数只清除指针,但不清除T类型的对象。
要解决此原始指针问题,如果您有C ++ 11编译器,则可以依赖std::shared_ptr
或std::unique_ptr
代替原始指针
答案 1 :(得分:4)
在这种情况下或其他类型的UB中我是否会出现内存泄漏?
假设T
表现良好 * ,则不会出现内存泄漏,并且行为已完全定义。
C ++标准保证它将运行std::vector<T>
的析构函数,清理已分配给该向量的内存。此外,C ++标准保证如果push_back()
抛出异常,该函数没有效果,这意味着你的向量仍然可以安全地销毁。
* 表现良好我的意思是T
应该释放与之相关的资源。 表现良好的T
的一个常见示例是一个简单的指针:它不会用于清理。
答案 2 :(得分:1)
表达式new T()
通常会做两件事:
如果构造函数抛出异常(并且堆栈中的某些内容正在处理异常),则在异常向上传播到堆栈之前,将释放在步骤1中分配的内存。这里没有内存泄漏。
回答上一级发生的事情需要澄清问题中的代码,因为矢量的类型与其使用不匹配。
答案 3 :(得分:0)
如果抛出异常,它会恢复您的函数调用,直到它到达try
catch
块。
如果此调用与您的main之间没有尝试捕获,则程序将以错误值退出。
您可以像这样管理它:
std::vector v;
try
{
init(v, 10, 20);
// Init was successful, continue execution here
}
catch (const std::exception& exception)
{
// An exception was thrown in init or after
std::cerr << exception.what() << std::endl; // Print exception error message
}
无论如何,如果你在try-catch块之前声明它,你的矢量不会受到任何内存泄漏的影响。