make_shared是一个尝试捕获 - 范围问题

时间:2015-08-07 19:09:16

标签: c++

我需要分配内存,但是我想在try / catch中执行此操作,但是引入了一个新的范围,其中一旦我超出了try-scope,变量就不可用了。解决这个问题的最佳方法是什么?

try {
    auto something = std::make_unique<SomeClass>;
} 
catch (std::bad_alloc) {
    ...
}
// ... lots of code I don't want to include in the try/catch-scope.
something.callSomeMethod();

如何解决这个问题?

4 个答案:

答案 0 :(得分:2)

有一个特定的原因,你在做什么不应该工作。如果您编写的代码按照您编写的方式工作,那么您将在null对象上调用PHASE_COMMENT。正如Benjamin Lindley所说的那样,正确的方法是将代码放在try块中。这样变量就是范围内的,但方法调用只有在没有错误的alloc引发异常的情况下才会发生。

答案 1 :(得分:2)

对于后代,如果您需要在try块中执行其他操作,会导致无效指针(因为,如上所述,有一个原因是什么?你试图做的不起作用)。如果您正尝试执行其他操作并且仍希望之后在something上执行操作,则以下代码将执行您想要的操作:

#include <iostream>

#include <memory>
#include <utility>

using namespace std;

int main()
{
    class SomeClass { public: int a; void callSomeMethod() const {} };

    std::unique_ptr<SomeClass> something{};

    try {
        something = std::move(std::make_unique<SomeClass>());

        // operation that might throw other_exception
    }
    catch (const other_exception& e) {
        std::cout << "bad" << std::endl;
    }
    // ... lots of code I don't want to include in the try/catch-scope.
    something->callSomeMethod();

    return 0;
}

答案 2 :(得分:1)

正如其他答案所提到的,您的代码通常应该在try/catch块内,因为如果捕获到异常它没有任何意义。我不确定您不希望在try/catch中包含代码的原因是什么,因为您暗示something.callSomeMethod()取决于lots of code,而lots of code取决于std::make_unique。如果lots of code不依赖,则可以将std::make_unique推迟到lots of code之后。

我认为可能值得澄清,例外的目的是中止和处理特殊情况。特殊情况是可能会影响以下代码的执行。因此,任何受影响的代码或依赖于它的传递代码都应包含在try/catch块中。根据定义,这是最小范围,它是您应该使用的范围。没什么,没什么。

有时处理异常的代码可以在抛出异常的函数之间共享,但通常最好缩小范围并为每个代码编写必要的特定处理代码。

值得注意的是,std::bad_alloc几乎无法做任何事情,因此通常不值得捕捉。此外,除非您有其他理由,否则通常应通过引用来捕获异常。所以,你的代码应该看起来像这样......

try {

    auto something = std::make_unique<SomeClass>;    

    // ... lots of code I don't want to include in the try/catch-scope.

    something.callSomeMethod();
}

catch (std::exception& e) {

    // you dun goofed...
}

答案 3 :(得分:0)

如果你真的必须在try / catch块之外使用something(不,你真的不能,但如果你坚持......)那么最好不要给自己一个段错误。

在null unique_ptr上调用方法是一种确定的灾难方法,而且unique_ptr的初始化需要不必要的内存分配。

另一种方法是使用boost :: optional:

#include <iostream>

#include <boost/optional.hpp>

using namespace std;

int main()
{
    class SomeClass { public: int a; void callSomeMethod() const {} };

    boost::optional<SomeClass> something{};

    try {
        something = SomeClass();

        // operation that might throw other_exception
    }
    catch (const std::exception& e) {
        std::cout << "bad" << std::endl;
    }
    // ... lots of code I don't want to include in the try/catch-scope.
    if (something) {
        something.get().callSomeMethod();
    }
    return 0;
}