Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在异常处理中避免复制_C++_Exception Handling - Fatal编程技术网

C++ 在异常处理中避免复制

C++ 在异常处理中避免复制,c++,exception-handling,C++,Exception Handling,我可以通过以下方式避免复制对象吗 MyClass Obj; try { throw &Obj; } catch(MyClass *a) { } 避免复制异常对象的唯一方法是抛出指向该对象的指针,正如您在示例中所做的那样。您必须确保对象是静态的或堆分配的,而不是在抛出期间离开代码块后将消失的本地对象 编辑:另一种方法浮现在脑海中。您可以使用指针作为成员创建自己的异常类(该类应派生自std::exception或其子类之一),然后抛出该异常类。如果使用智能指针,例如共享\u p

我可以通过以下方式避免复制对象吗

MyClass Obj;

try {
    throw &Obj;
}
catch(MyClass *a) {

}

避免复制异常对象的唯一方法是抛出指向该对象的指针,正如您在示例中所做的那样。您必须确保对象是静态的或堆分配的,而不是在抛出期间离开代码块后将消失的本地对象


编辑:另一种方法浮现在脑海中。您可以使用指针作为成员创建自己的异常类(该类应派生自
std::exception
或其子类之一),然后抛出该异常类。如果使用智能指针,例如
共享\u ptr
,则不必担心所包含对象的生存期。

它在语法上是正确的,并且避免了复制,因为引用正在传递。但是,通常会构造一个标准的无名异常对象,并被
catch
语句捕获。

如果该对象的复制成本太高,则不应将其作为异常抛出-句号。异常类应该相当简单和轻量级。而且您应该始终通过引用(可能通过const引用)捕获异常—捕获指针是一种糟糕的风格。因此,最好编写代码:

try {
    throw MyClass();
}
catch( const MyClass & a) {
}
针对您的评论,我们:

struct A {
    A() {}
    private:
    A( const A & ) {}
};

int main() {
    throw A();
}
这应该是一个错误。但是你不应该禁止复制你想作为异常抛出的类——为什么要这样做?

不要这样做

考虑一下这个计划:

#include <iostream>
#define X() (std::cout << __FUNCTION__ << "\n")

struct MyClass {
 MyClass() { X(); }
 ~MyClass() { X(); }
};

void f() {
 MyClass Obj;
 throw &Obj;
}

int main() {
 try {
  f();
 } catch(MyClass *a) {
  X();
 }
}

请注意,指向的对象在程序进入catch块之前被销毁。这意味着我们不能在catch块中取消对
a
的引用,这严重限制了它的用途

但是,如果Obj是在与抛出相同的函数中声明的,那么发生的事情是未定义的,或者更糟,因为当您捕获时Obj超出了范围it@Neil,我不会说这是一个好主意,但微软的MFC侥幸逃脱了它。还有资源管理的问题“谁清理堆上浮动的异常对象更有效的C++有一个很好的概述,为什么抛出和捕获指针是个坏主意——它是第一个ED中的项目13。@这不是一个真正的终生问题。请不要鼓励新手去幻想抛出共享指针。在C++中使用异常的正确方法是抛出值并捕获const引用。是的,我知道指针是值,在挑剔者开始之前。与抛出异常并捕获异常相关的开销相比,对象复制算不了什么。以及为此生成的代码量。。。所以别担心。如果您想抛出不可复制的对象,或者复制对象的成本非常高,那么您根本不应该将其用作异常对象。您是否可能希望抛出有关异常的上下文,例如是什么导致它或需要从事务中退出的数据?这可能会导致异常对象不是很轻。@请标记一些上下文,当然-我的异常类包含消息、文件名和行号。事务回退所需的数据-否。事务回退可以响应异常,但回退数据应存储在其他位置,如事务日志中。除此之外,您可能希望在非异常情况下撤销事务。在本例中,编译器是否会使用自己的特殊复制构造函数?我有它在私人部分,但我仍然可以编译它。嗯,好吧,它没有工作。但它是在我拥有的VC++8.0上编译的@用户嘎!但是你为什么不想让它被复制????????不,你不应该改变你的编译器(至少是这个问题),你应该改变你的设计。在这种情况下,使用
throw new MyClass()
可以让它工作。
MyClass
~MyClass
main