大多数人都说永远不会从析构函数中抛出异常 - 这样做会导致未定义的行为.Stroustrup指出"向量析构函数显式地为每个元素调用析构函数.这意味着如果元素析构函数抛出,向量破坏失败......实际上没有好的方法来防止从析构函数抛出的异常,所以库如果元素析构函数抛出",则不保证"(来自附录E3.2).
这篇文章似乎另有说法 - 抛出析构函数或多或少都没问题.
所以我的问题是 - 如果从析构函数抛出会导致未定义的行为,那么如何处理析构函数期间发生的错误?
如果在清理操作期间发生错误,您是否只是忽略它?如果它是一个可能在堆栈中处理但在析构函数中不正确的错误,那么从析构函数中抛出异常是否有意义?
显然,这类错误很少见,但可能.
我不确定这是编译器的问题还是我做错了.我正在使用Visual Studio 2013编译器.
我有一个类,我需要在构造函数初始化列表中获取大量资源,其中大部分都可以抛出异常.我在函数try块中包装了成员初始化列表,并在那里捕获了异常.但是我的程序仍然会中止,即使catch子句没有重新抛出异常.我不允许发布实际代码.所以我用这个等效的演示代码重现了这个问题.有人可以帮我解决这个问题吗?
#include <iostream>
using namespace std;
class A{
public:
A() try : i{ 0 }{ throw 5; }
catch (...){ cout << "Exception" << endl; }
private:
int i;
};
int main(){
A obj;
}
Run Code Online (Sandbox Code Playgroud)
在执行此代码时,我得到一个Windows警报"abort()已被调用".所以我猜系统将此视为未捕获的异常并调用terminate().
另一方面,如果我在try(catch)块中的main()中包装对象的构造,则正确捕获异常并且程序正常终止.
有人可以告诉我,如果我在这里做错了吗?
此代码int在构造Dog类中的对象时抛出异常UseResources.该int异常由正常捕获try-catch块和代码输出:
Cat()
Dog()
~Cat()
Inside handler
Run Code Online (Sandbox Code Playgroud)
#include <iostream>
using namespace std;
class Cat
{
public:
Cat() { cout << "Cat()" << endl; }
~Cat() { cout << "~Cat()" << endl; }
};
class Dog
{
public:
Dog() { cout << "Dog()" << endl; throw 1; }
~Dog() { cout << "~Dog()" << endl; }
};
class UseResources
{
class Cat cat;
class Dog dog;
public:
UseResources() : …Run Code Online (Sandbox Code Playgroud) 我有一个类,它保存一个析构函数可以抛出的对象(它实际上是一个 tbb::task_group,但为了简单起见,我在这里将其命名为 MyObject)。
代码是这样的:
#include <stdexcept>
class MyObject {
public:
MyObject() {}
~MyObject() noexcept(false) {}
};
class A {
public:
A() {}
virtual ~A() {}
};
class B : public A {
public:
B() : A() {}
~B() {}
private:
MyObject _object;
};
Run Code Online (Sandbox Code Playgroud)
并且编译器会引发以下错误:
重写函数的异常规范比基本版本更宽松
我不喜欢在整个代码中传播 noexcept(false) 的想法,因此我正在考虑使用指向 MyObject 的原始指针,并在析构函数之外删除它们(例如在 Close 函数中)。
处理这种情况的最佳方法是什么?
只是一个简单的问题.两者之间有什么区别吗?
void f(Foo x) try
{
...
}
catch(exception& e)
{
...
}
Run Code Online (Sandbox Code Playgroud)
和
void f(Foo x)
{
try { ... }
catch (exception& e)
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
?
如果不是,为什么函数尝试块(构造函数的初始化列表的情况被放在一边)?如果复制构造函数Foo在x传递给异常时抛出异常会发生什么f?
我最近的任务是在代码的一部分中查找内存泄漏.泄漏最终出现在特定对象的析构函数中......我发现了一些非常奇怪的东西.一位前同事写道:
File::~File()
try
{
Clear();
}
catch (...)
{
Log("caught exception");
}
Run Code Online (Sandbox Code Playgroud)
文件类继承自一些基类.我的第一个问题是:这是严格合法的C++吗?它在Visual Studio 2008中编译,但我向几个朋友/同事展示了它们,并且它们相当惊恐,它的工作原理.
但它实际上并没有按预期工作:这个对象继承的基类有一个现在永远不会被调用的析构函数(而不是如果你只是将析构函数包装在常规方法块中,将try/catch作为一部分)那个方法).
任何人都可以尝试解释为什么允许这样做,以及为什么没有调用基类析构函数?这里的析构函数并没有抛出.
我在阅读Stroustrup的“编程-使用C ++的原理和实践”时发现,他包含了一个没有花括号的函数,却没有解释自己,网上的人说这是不可能的。
我已经编译了代码,并且可以正常工作。
void f()
try {}
catch(...) {}
Run Code Online (Sandbox Code Playgroud)
我希望从中得到一个编译器错误,但是我没有,并且它工作正常。我正在使用C ++ 17。
我读了这段代码(由Bjarne Stroustrup撰写).我很困惑... main函数体不在{},函数不返回值(as int).它有效......为什么?
#include "std_lib_facilities.h"
int main()
try
{
cout<< "please enter two floating-point values separated by an operator\n The operator can be + - * or / : ";
double val1 = 0;
double val2 = 0;
char op = 0;
while (cin>>val1>>op>>val2) { // read number operation number
string oper;
double result;
switch (op) {
case '+':
oper = "sum of ";
result = val1+val2;
break;
case '-':
oper = "difference …Run Code Online (Sandbox Code Playgroud) 从相关的c ++标准部分:
引用构造函数的函数try-block的处理程序中的对象的任何非静态成员或基类,或该对象的析构函数导致未定义的行为.
例如.
T::~T()
{
try {
this->nonstatic_member; // iff I read the quote correctly
} catch( ... ) {
}
}
Run Code Online (Sandbox Code Playgroud)
那为什么这个未定义的行为?
我有一个类,其构造函数可能会抛出异常.这里有一些代码可以捕获异常:
try {
MyClass instance(3, 4, 5);
}
catch (MyClassException& ex) {
cerr << "There was an error creating the MyClass." << endl;
return 1;
}
Run Code Online (Sandbox Code Playgroud)
但是当然,try/catch之后没有代码可以看到,instance因为它现在超出了范围.解决这个问题的一种方法是分别声明和定义instance:
MyClass instance;
try {
MyClass instance(3, 4, 5);
}
...
Run Code Online (Sandbox Code Playgroud)
除了我的类没有适当的零参数构造函数.事实上,这里的这个案例是唯一一个这样的构造函数甚至有意义的案例:MyClass对象是不可变的,因为它的数据成员在构造之后都没有变化.如果我要添加一个零参数构造函数,我需要引入一些类似的实例变量is_initialized_,然后检查每个方法以确保该变量true在继续之前.对于这样一个简单的模式来说,这似乎太过冗长.
处理这种事情的惯用方法是什么?我是否需要将其填充并允许在初始化之前声明我的类的实例?
我正在阅读Stroustrup的编程:原理和实践,并遇到了这段代码:
int main()
try {
// our program
return 0; //0 indicates success
}
catch (exception& e) {
cerr << "error: " <<e.what() <<'\n';
keep_window_open();
return 1; // 1 indicates failure
}
catch (...) {
cerr << "Oops: Unknown exception!\n";
keep_window_open();
return 2; //2 indicates failure
}
Run Code Online (Sandbox Code Playgroud)
起初我认为第一行称为主函数(其中包含代码的核心,并写在其他地方).然后我们只是尝试捕获main()内部可能发生的错误.但如果是这样的话,为什么在try块中说"我们的程序"呢?这让我觉得这段代码定义了main().但如果是这样,那么支架在哪里呢?也就是说,为什么不在int main() {第一线呢?
c++ ×11
c++11 ×2
exception ×2
constructor ×1
destructor ×1
function ×1
raii ×1
scope ×1
syntax ×1
try-catch ×1