有没有人曾经使用过C++的"贴牌新品"?如果是这样,那该怎么办?在我看来,它只对内存映射硬件有用.
大多数人都说永远不会从析构函数中抛出异常 - 这样做会导致未定义的行为.Stroustrup指出"向量析构函数显式地为每个元素调用析构函数.这意味着如果元素析构函数抛出,向量破坏失败......实际上没有好的方法来防止从析构函数抛出的异常,所以库如果元素析构函数抛出",则不保证"(来自附录E3.2).
这篇文章似乎另有说法 - 抛出析构函数或多或少都没问题.
所以我的问题是 - 如果从析构函数抛出会导致未定义的行为,那么如何处理析构函数期间发生的错误?
如果在清理操作期间发生错误,您是否只是忽略它?如果它是一个可能在堆栈中处理但在析构函数中不正确的错误,那么从析构函数中抛出异常是否有意义?
显然,这类错误很少见,但可能.
C++完全是关于内存所有权
Aka" Ownership Semantics "
一块动态分配的内存的所有者负责释放该内存.所以这个问题真的变成了拥有记忆的人.
在C++中,所有权都是由RAW指针包含在内部的类型记录的,因此在一个好的(IMO)C++程序中,很少见[RARE并非永远]看到RAW指针传递(因为RAW指针没有推断的所有权因此我们不能告诉谁拥有记忆,因此如果没有仔细阅读文件,你无法分辨谁负责所有权).
相反,很少看到RAW指针存储在类中,每个RAW指针都存储在自己的SMART指针包装器中.(注意:如果你没有一个对象,你不应该存储它,因为你不知道什么时候它会超出范围并被销毁.)
所以问题是:
让我们为每个答案保留一种语义所有权,这样他们就可以单独上下投票
从概念上讲,智能指针很简单,而且简单易用.我已经看过许多尝试过的实现,但总是以某种方式打破它们,这对于随意使用和示例来说并不明显.因此,我建议始终使用经过良好测试的"智能指针",而不是自己动手.std :: auto_ptr或其中一个提升智能指针似乎涵盖了我的所有需求.
单身人士拥有该物品.
但允许转让所有权.
用法:
======
这允许您定义显示所有权显式转移的接口.
单身人士拥有该物品.
不允许转让所有权.
用法:
======
用于显示明确的所有权.
对象将被析构函数或显式重置时销毁.
多个所有权.
这是一个简单的引用计数指针.当引用计数达到零时,对象被销毁.
用法:
======
当对象可以有多个owers,其生命周期无法在编译时确定.
与shared_ptr <T>一起使用.
在指针循环可能发生的情况下.
用法:
======
用于在仅循环维护共享引用计数时停止保留对象的周期.
这是一个初学者的问题,但我很长一段时间没有做过C++,所以这里......
我有一个包含动态分配数组的类,比方说
class A
{
int* myArray;
A()
{
myArray = 0;
}
A(int size)
{
myArray = new int[size];
}
~A()
{
// Note that as per MikeB's helpful style critique, no need to check against 0.
delete [] myArray;
}
}
Run Code Online (Sandbox Code Playgroud)
但现在我想创建一个动态分配的这些类的数组.这是我目前的代码:
A* arrayOfAs = new A[5];
for (int i = 0; i < 5; ++i)
{
arrayOfAs[i] = A(3);
}
Run Code Online (Sandbox Code Playgroud)
但这种情况非常糟糕.因为在循环迭代完成时,A(通过A(3)调用)创建的新对象会被破坏for,这意味着myArray该A实例的内部delete []变为-ed.
所以我认为我的语法必定是非常错误的?我想有一些看起来像矫枉过正的修复,我希望避免:
A …处理异常涉及很多相对性.除了低级别的API,其中异常包括从硬件和操作系统引发的错误,有一个阴暗的区域,程序员决定什么构成异常,什么是正常情况.
你如何决定何时使用例外?您是否有关于例外的一致政策?
首先,根据C++标准,使用delete分配的任何内容new[]都是未定义的行为.
在Visual C++ 7中,这种配对可能导致两种后果之一.
如果类型new []'ed有简单的构造函数和析构函数VC++只是使用new而不是new[]和使用delete该块工作正常 - new只调用"分配内存",delete只调用"空闲内存".
如果new []'ed类型有一个非平凡的构造函数或析构函数,则无法完成上述技巧 - VC++ 7必须调用恰当数量的析构函数.因此它预先在数组中size_t存储元素的数量.现在,地址返回的地址new[]到第一个元素,而不是块的开头.因此,如果delete使用它只调用第一个元素的析构函数和调用"空闲内存",其地址不同于"分配内存"返回的地址,这导致HeapFree()内部的一些错误指示我怀疑是指堆腐败.
然而,每个人都可以阅读使用deleteafter new[]导致内存泄漏的错误陈述.我怀疑任何大小的堆损坏都比仅为第一个元素调用析构函数并且可能没有调用的析构函数没有释放堆分配的子对象这一事实重要得多.
如何使用delete之后new[]可能只会导致某些C++实现中的内存泄漏?
我刚刚学习了名为"placement new"的C++结构.它允许您精确控制指针指向内存的位置.它看起来像这样:
#include <new> // Must #include this to use "placement new"
#include "Fred.h" // Declaration of class Fred
void someCode()
{
char memory[sizeof(Fred)];
void* place = memory;
Fred* f = new(place) Fred(); // Create a pointer to a Fred(),
// stored at "place"
// The pointers f and place will be equal
...
}
Run Code Online (Sandbox Code Playgroud)
(来自C++ FAQ Lite的
例子)在这个例子中,thisFred 的指针将等于place.
我已经看到它在我们团队的代码中使用过一次或两次.根据您的经验,这个构造能够实现什么?其他指针语言是否有类似的结构?对我来说,它似乎让人联想equivalence到FORTRAN,它允许不同的变量占据内存中的相同位置.
传统上,在C++中,您将在构造函数中创建任何依赖项,并在析构函数中删除它们.
class A
{
public:
A() { m_b = new B(); }
~A() { delete m_b; }
private:
B* m_b;
};
Run Code Online (Sandbox Code Playgroud)
这种技术/资源获取模式,它有一个共同的名称吗?
我很确定我已经在某处读过它但现在找不到它.
编辑:
正如许多人所指出的,这个类是不完整的,应该真正实现一个复制构造函数和赋值运算符.
最初,我故意将其遗漏,因为它与实际问题无关:模式的名称.但是,为了完整性和鼓励良好实践,接受的答案就是它.
c++ ×7
destructor ×2
exception ×2
new-operator ×2
raii ×2
equivalence ×1
memory ×1
pointers ×1