C++ 这种资源泄漏是由可能的评估命令提供的还是Scott Meyers错了?
我在Scott Meyers所著的C++ 这种资源泄漏是由可能的评估命令提供的还是Scott Meyers错了?,c++,c++11,memory-leaks,C++,C++11,Memory Leaks,我在Scott Meyers所著的高效现代C++14一书中读到了关于std::shared\ptr。以下是一段代码,作者说潜在的资源泄漏可能是: int computePriority(); // this function always throw an exception // ... processWidget(std::shared_ptr<Widget>(new Widget), // (S.M): potentital computePrior
高效现代C++14
一书中读到了关于std::shared\ptr
。以下是一段代码,作者说潜在的资源泄漏可能是:
int computePriority(); // this function always throw an exception
// ...
processWidget(std::shared_ptr<Widget>(new Widget), // (S.M): potentital
computePriority()); // resource
// leak
int computePriority();//此函数始终引发异常
// ...
processWidget(std::shared_ptr(新小部件),//(S.M):潜在的
computePriority());//资源
//漏
Scott Meyers说,computePriority()
函数可以在new Widget
和std::shared_ptr(expr)
之间调用,计算表达式时,将考虑new
导致的内存泄漏。是否应该有一个序列点可以保证如果计算了新小部件
表达式,那么接下来将计算std::shared_ptr(expr)
?我这样想是因为在我看来它是正确的:sequence point instd::shared_ptr(expr)
将不按顺序计算它的所有参数(子表达式),并使共享指针准备就绪,然后执行其他操作(不按顺序计算其他参数)。如果这是不真实的,Scott Meyers
是正确的(显然,我仍然相信他)
,这种行为是否不正确
有没有一条规则可以解释为什么这是可能的?我不擅长序列点,但告诉我序列点的人说这应该是正确的
是否应该有一个序列点可以保证如果计算了新小部件
表达式,那么接下来将计算std::shared_ptr(expr)
不,事实并非如此。在新小部件
和共享ptr
构造之间没有序列点
看。(顺便说一句,这在C++11中是一个过时的术语,但逻辑基本保持不变。)
序列点出现…
和&
(逻辑和
)、|
(逻辑或
)的左右操作数之间
只要构造函数不会抛出坏的alloc,在构造函数中使用
新的就可以了。
make_shared
没有此问题(请参阅)
是否应该有一个序列点可以保证如果计算新的小部件表达式,那么接下来将计算std::shared_ptr(expr)
嗯,是的。分号很好,因为它标志着完整表达式的结束
auto ptr = new Widget; // may throw bad_alloc
std::shared_ptr<Widget> shared(ptr); // may throw bad_alloc
processWidget(std::move(shared), computePriority()); // computePriority may throw
由于两个函数调用从不交错,因此可以在make_shared
之前调用computePriority()
,反之亦然,如果其中一个抛出,则不会出现内存泄漏。但是,在抛出调用的过程中使用try-catch
块,而不是通过内联使其发生硬崩溃,这可能符合您的利益。排序并不意味着即时性。
(我的起床顺序是在上班前安排的,即使我穿衣并在其间吃早餐。)
参数的计算不按顺序排列
这也不是说一个参数必须在另一个参数之前被完全评估,不管顺序如何
也就是说,分配在shared_ptr构造函数之前进行排序,但是这两个参数都没有按照其他参数进行排序,并且不能保证在分配和构造函数调用之间不会发生任何事情 “完全好”是不正确的。构造函数被允许抛出。如果您使用此构造函数,您应该准备捕获一个错误的\u alloc
。
processWidget(std::make_shared<Widget>(), computePriority());