我需要分配内存,但是我想在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();
如何解决这个问题?
答案 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;
}