C++ 这种资源泄漏是由可能的评估命令提供的还是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

我在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
              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 in
std::shared_ptr(expr)
将不按顺序计算它的所有参数(子表达式),并使共享指针准备就绪,然后执行其他操作(不按顺序计算其他参数)。如果这是不真实的,
Scott Meyers
是正确的(显然,我仍然相信他) ,这种行为是否不正确

有没有一条规则可以解释为什么这是可能的?我不擅长序列点,但告诉我序列点的人说这应该是正确的

是否应该有一个序列点可以保证如果计算了
新小部件
表达式,那么接下来将计算
std::shared_ptr(expr)

不,事实并非如此。在
新小部件
共享ptr
构造之间没有序列点

看。(顺便说一句,这在C++11中是一个过时的术语,但逻辑基本保持不变。)

序列点出现

  • 在计算
    和&
    (逻辑
    )、
    |
    (逻辑
    )的左右操作数之间

  • 三元“问号”运算符的第一个操作数的求值与第二个或第三个操作数之间

  • 在完整表达的结尾

  • 在函数调用中输入函数之前

  • 在函数返回时

  • 在初始值设定项的末尾

  • 在每个声明程序序列中的每个声明程序之间

  • 8.在与输入/输出转换格式说明符关联的操作之后

  • 请参阅以供参考
    只要构造函数不会抛出坏的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());