考虑用来解释一下这个典型的例子并不与前向声明做:
//in Handle.h file
class Body;
class Handle
{
public:
Handle();
~Handle() {delete impl_;}
//....
private:
Body *impl_;
};
//---------------------------------------
//in Handle.cpp file
#include "Handle.h"
class Body
{
//Non-trivial destructor here
public:
~Body () {//Do a lot of things...}
};
Handle::Handle () : impl_(new Body) {}
//---------------------------------------
//in Handle_user.cpp client code:
#include "Handle.h"
//... in some function...
{
Handle handleObj;
//Do smtg with handleObj...
//handleObj now reaches end-of-life, and BUM: Undefined behaviour
}
Run Code Online (Sandbox Code Playgroud)
我从标准中了解到这个案例正朝向UB,因为Body的析构函数是非常重要的.我想要了解的是这个的根本原因.
我的意思是,问题似乎是由Handle的dtor内联的事实"触发",因此编译器执行类似下面的"内联扩展"(这里几乎是伪代码).
inline Handle::~Handle()
{ …Run Code Online (Sandbox Code Playgroud) c++ destructor memory-management forward-declaration delete-operator
我在我的程序中制作了一个小内存泄漏查找程序,但我的方法是重载new和delete(以及new []和delete [])似乎没有做任何事情.
void* operator new (unsigned int size, const char* filename, int line)
{
void* ptr = new void[size];
memleakfinder.AddTrack(ptr,size,filename,line);
return ptr;
}
Run Code Online (Sandbox Code Playgroud)
我重载的方式new显示在上面的代码片段中.我想这是操作员返回void*的东西,但我不知道该怎么办.
我希望有一个简单的问题 - 当异常发生时,如何在try块中分配一个空闲内存?请考虑以下代码:
try
{
char *heap = new char [50];
//let exception occur here
delete[] heap;
}
catch (...)
{
cout << "Error, leaving function now";
//delete[] heap; doesn't work of course, heap is unknown to compiler
return 1;
}
Run Code Online (Sandbox Code Playgroud)
如何在分配堆之后释放内存并在调用之前发生异常delete[] heap?在这些try .. catch块中是否有规则不在堆上分配内存?
我正在玩内存动态分配,但我不明白.当用new语句分配一些内存时,我应该能够破坏指针指向使用的内存delete.
但是当我尝试时,这个delete命令似乎不起作用,因为指针指向的空间似乎没有被清空.
让我们以这个真正基本的代码为例:
#include <iostream>
using namespace std;
int main()
{
//I create a pointer-to-integer pTest, make it point to some new space,
// and fulfill this free space with a number;
int* pTest;
pTest = new int;
*(pTest) = 3;
cout << *(pTest) << endl;
// things are working well so far. Let's destroy this
// dynamically allocated space!
delete pTest;
//OK, now I guess the data pTest pointed to has been destroyed …Run Code Online (Sandbox Code Playgroud) 在C++ 03标准中,我看到:
5.3.5删除
2如果操作数具有类类型,则通过调用上述转换函数将操作数转换为指针类型,并使用转换后的操作数代替本节其余部分的原始操作数.在任一替代方案中,如果操作数的值
delete是空指针,则操作无效.在第一个备选(删除对象)中,操作数的值delete应该是指向非数组对象的指针或指向表示此类对象的基类的子对象(1.8)的指针(第10节).如果不是,则行为未定义.在第二种方法(删除数组)中,操作数的delete值必须是由前一个数组new-expression产生的指针值.72)如果不是,则行为是未定义的.
在C++ 11 Draft Standard(N3337)中,我看到:
5.3.5删除
2如果操作数具有类类型,则通过调用上述转换函数将操作数转换为指针类型,并使用转换后的操作数代替本节其余部分的原始操作数.在第一个替代(删除对象)中,操作数的值
delete可以是空指针值,指向由前一个新表达式创建的非数组对象的指针,或指向表示基础的子对象(1.8)的指针这类对象的类别(第10条).如果不是,则行为未定义.在第二个备选(删除数组)中,delete的操作数的值可以是空指针值或由先前数组new-expression产生的指针值.如果不是,则行为未定义.
我已经强调了两个标准中规范之间的差异.我觉得奇怪的是,2003标准更加强调必须如何处理NULL指针,而2011标准没有说明实现必须做什么.
C++ 11标准的措辞是否在草案标准和实际标准之间发生了变化?如果是这样,怎么样?
如果标准草案的措辞在实际标准中保持不变,那么在2003年和2011年之间将强有力的陈述改为几乎没有任何理由的理由是什么?
使用时分配数组时new [],为什么不能从指针中找出该数组的大小?它必须在运行时delete []知道,否则不知道要释放多少内存.
除非我错过了什么?
C++ 14引入了"大小"版本operator delete,即
void operator delete( void* ptr, std::size_t sz );
Run Code Online (Sandbox Code Playgroud)
和
void operator delete[]( void* ptr, std::size_t sz );
Run Code Online (Sandbox Code Playgroud)
通过N3536阅读,似乎引入了这些运营商以提高性能.我知道典型的分配器operator new"存储"大容量内存的大小,这就是典型的operator delete"知道"多少内存返回到免费商店.
我不确定为什么"大小"版本operator delete会在性能方面有所帮助.唯一可以加快速度的是从控制块开始减少关于大小的读取操作.这确实是唯一的优势吗?
其次,我该如何处理阵列版本?AFAIK,分配的数组的大小不是简单的sizeof(type)*number_elements,但可能会分配一些额外的字节,因为实现可能会使用这些字节作为控制字节.operator delete[]在这种情况下我应该传递什么"大小" ?你能提供一个简短的使用例子吗?
如果是这样,为什么下面的代码会给我警告
注意:即使在定义类时声明析构函数也不会调用析构函数或特定于类的运算符delete
?
struct C;
int main()
{
C *c = nullptr;
delete c;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我明白为什么它会在一般情况下是不确定的行为,如果C有非平凡/虚析构函数,但不标准的保证/定义delete上nullptr始终是一个noop不管情况如何?
重申:我具体询问指向不完整类型的指针的情况nullptr!
std::allocator是对底层内存模型的抽象,它包含了调用new和的功能delete. delete虽然不需要大小,但是deallocate() 需要它.
void deallocate(T*p,std :: size_t n);
"参数n必须等于最初生成p的allocate()调用的第一个参数;否则,行为是未定义的."
为什么?
现在我要么在解除分配之前进行额外的计算,要么开始存储我传递给分配的大小.如果我没有使用分配器,我就不必这样做了.
我搜索了StackOverflow但找不到这个问题的答案.
假设我有一个std::vector<Day *> vector_day- 即指向Day对象的指针向量.现在我push_back到vector_day很多元素:
vector_day.push_back(new Day(12));
vector_day.push_back(new Day(99));
vector_day.push_back(new Day(71));
...
Run Code Online (Sandbox Code Playgroud)
现在在某些时候我不再需要了vector_day.什么是释放记忆的正确方法?
这是正确的方法:
for (std::vector<Day *>::iterator i = vector_day.begin(); i != vector_day.end(); ++i) {
delete *i;
}
Run Code Online (Sandbox Code Playgroud)
这不会使每次删除时的向量无效吗?我很迷茫.
c++ ×10
delete-operator ×10
new-operator ×3
memory ×2
allocator ×1
arrays ×1
c++03 ×1
c++11 ×1
c++14 ×1
containers ×1
destructor ×1
nullptr ×1
stl ×1
try-catch ×1
vector ×1