问题标签 [raii]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
3 回答
1928 浏览

c++ - 带有用 C 编写的库的智能指针

我将 C++ 与 OpenCV 库一起使用,这是一个库图像处理,尽管这与这个问题无关。目前我有一个设计决定要做。

OpenCV 是一个 C 库,其数据结构(例如 CvMat)被声明为结构。要创建它们,可以使用 cvCreateMat 之类的函数,要释放它们,请使用 cvReleaseMat 之类的函数。作为一名 C++ 程序员,我创建了一个特殊的cv_scoped类,当它超出范围时会自动调用 cvReleaseMat(如boost::scoped_ptr)。

我现在意识到的是,我希望我也可以使用auto_ptrand shared_ptrin case 。我只是觉得为自己cv_auto_ptrcv_shared_ptr班级编写代码是个坏主意,更不用说浪费时间了。所以我一直在寻找解决方案,我提出了三种可能性。

首先,我可以使用我已经创建的 cv_scoped 类。我将它重命名为cv_ptr然后使用智能指针,如下所示std::auto_ptr<cv_ptr>:不过,令人讨厌的是,我总是不得不取消引用两次:

我知道看起来我可以声明一个隐式转换,但实际上我不能——大多数 OpenCV 的函数都有参数 void*——所以不会调用隐式转换。我真的很想这样做,我不必做双重取消引用。

其次,我可以以某种方式覆盖operator delete。我不想覆盖全局运算符 delete,因为我只希望它适用于 CvMat(和其他一些)类型。但是,我无法更改库,因此无法添加operator delete到 CvMat 结构中。所以我不知道这将如何工作。

第三,我可以重写我自己的auto_ptr,scoped_ptrshared_ptr. 他们不是大班,所以不会太难,但我只是觉得这是糟糕的设计。如果我要这样做,我可能会按照以下方式做一些事情:

在我的情况下你会怎么做?请帮我解决这个问题。

0 投票
9 回答
7236 浏览

c++ - 在 C++ 中实现智能指针的最佳方法是什么?

我一直在评估各种智能指针实现(哇,那里有很多),在我看来,它们中的大多数可以分为两大类:

1) 此类别对引用的对象使用继承,以便它们具有引用计数,并且通常实现 up() 和 down()(或它们的等价物)。IE,要使用智能指针,您指向的对象必须从 ref 实现提供的某个类继承。

2) 此类别使用辅助对象来保存引用计数。例如,智能指针不是直接指向一个对象,而是实际上指向这个元数据对象……谁有引用计数和 up() 和 down() 实现(并且谁通常提供指针指向的机制获取指向的实际对象,以便智能指针可以正确实现运算符->())。

现在, 1 有一个缺点,它强制您希望引用 count 的所有对象都从一个共同的祖先继承,这意味着您不能使用它来引用您无法控制源代码的 count 对象到。

2 的问题是由于计数存储在另一个对象中,如果您曾经遇到将指向现有引用计数对象的指针转换为引用的情况,您可能有一个错误(IE,因为计数不在实际对象,新引用无法获取计数...引用到引用复制构造或赋值很好,因为它们可以共享计数对象,但是如果您必须从指针转换,您重新完全冲洗)...

现在,据我了解, boost::shared_pointer 使用机制 2,或类似的东西......也就是说,我无法完全决定哪个更糟!我只在生产代码中使用过机制 1……有人对这两种风格都有经验吗?或者也许还有另一种比这两种方法更好的方法?

0 投票
3 回答
808 浏览

c++ - 什么时候适合使用 C++ 异常?

我正在尝试设计一个需要动态分配一些内存的类..

我计划在构建过程中分配它需要的内存,但是我该如何处理失败的内存分配呢?我应该抛出异常吗?我在某处读到异常应该只用于“例外”情况,而内存不足对我来说似乎不是例外情况。

我是否应该在单独的初始化例程中分配内存并检查故障,然后优雅地销毁类实例?

或者我应该改用异常?如果这些内存分配失败,该类将没有任何有用的事情可做。


编辑:共识似乎是内存不足是一个例外情况。

将看到如何去做这件事.. 谢谢.. :)

0 投票
4 回答
1454 浏览

garbage-collection - 垃圾收集的副作用?

这可能是一个非常容易解决的问题,但我是那种看到什么东西粘在墙上的人。对于垃圾收集运行时提供的内存和生命周期管理的所有好处,是否存在由应用程序与其垃圾收集器之间的竞争条件导致的程序不确定性的明显案例?是否出现了针对此类事物的防御性编程格式塔?当然,习惯于 RAII 的程序员在 GC 面前必须吸取教训。

0 投票
4 回答
1693 浏览

java - 在 Java 中是否可以进行类似 C++ 的资源管理

在 C++ 中,我们有资源获取即初始化(RAII) 模式,它极大地简化了资源管理。这个想法是为任何类型的资源提供一些包装对象。包装对象的析构函数然后负责释放资源,当它超出其范围时。例如:

最常见的用法是智能指针。但是,还有许多其他类型的资源(文件、互斥体、套接字等)可以以完全相同的方式进行管理。

在 Java 中,不必担心内存管理。但所有其他类型的资源仍然存在。有finally块,但是它的使用相当不方便,尤其是当可以抛出许多不同的异常时。

所以,我的问题是,是否有任何 Java 模式提供与 C++ RAII 等效的功能?如果没有,请分享您在该领域的最佳实践(而不是 finally,除非它使用了一些复杂的方式)。

0 投票
10 回答
16958 浏览

c++ - 理解术语和概念的含义 - RAII (Resource Acquisition is Initialization)

各位 C++ 开发人员能否给我们一个好的描述 RAII 是什么,为什么它很重要,以及它是否可能与其他语言有任何关系?

知道一点。我相信它代表“资源获取就是初始化”。然而,这个名字与我(可能不正确)对 RAII 的理解不符:我的印象是 RAII 是一种在堆栈上初始化对象的方式,这样,当这些变量超出范围时,析构函数将自动被调用导致资源被清理。

那么为什么不称为“使用堆栈触发清理”(UTSTTC:)?你如何从那里到达“RAII”?

你怎么能在堆栈上做一些东西来清理堆上的东西呢?另外,是否存在不能使用 RAII 的情况?您是否曾经发现自己希望进行垃圾收集?至少一个垃圾收集器可以用于某些对象,同时让其他对象得到管理?

谢谢。

0 投票
5 回答
84622 浏览

c++ - 我需要手动关闭 ifstream 吗?

close()使用时需要手动调用std::ifstream吗?

例如,在代码中:

我需要file.close()手动调用吗?不应该ifstream使用RAII来关闭文件吗?

0 投票
5 回答
478 浏览

c++ - RAII 和未初始化的值

只是一个简单的问题:

如果我有一个简单的向量类:

RAII 概念在这里也适用吗?即提供一个构造函数来将所有值初始化为某些值(以防止使用未初始化的值)。

编辑或提供一个构造函数,该构造函数明确要求用户在对象可以被实例化之前初始化成员变量。

IE

应该使用 RAII 来帮助程序员忘记在使用之前初始化值,还是开发人员的责任?

或者这是看待 RAII 的错误方式?

我故意让这个例子简单得可笑。我真正的问题是回答一个复合类,例如:

正如你所看到的......如果我必须编写一个构造函数来初始化每个成员,那是相当乏味的。

想法?

0 投票
10 回答
1413 浏览

c++ - C++ RAII 不工作?

我刚刚开始使用 C++ 中的 RAII 并设置了一个小测试用例。要么我的代码很混乱,要么 RAII 不工作!(我猜是前者)。

如果我运行:

除了注释掉的例外,我得到:

正如预期的那样,但除了我得到:

所以我的对象即使超出范围也不会被破坏。这不是 RAII 的全部基础吗?

非常感谢指点和更正!

0 投票
6 回答
393 浏览

c++ - 什么可能是不在 C++ 中使用括号类的原因?

通常需要完成以下任务:更改某物的状态,执行操作,然后将状态更改回原始状态。例如,在 Win32 GDI 中,需要更改背景颜色,然后进行一些绘图,然后将颜色更改回来。

它可以直接完成:

或者通过一个括号类,它将在构造函数中进行前向更改和在析构函数中进行后向更改:

括号类的优点是显而易见的——如果在更改之间引发异常,则更改将正确恢复。有什么缺点?