我之后,说
Foo* array = new Foo[N];
我总是这样删除它
delete[] array;
但是,有时候我这样看过:
delete[N] array;
由于它似乎在编译和工作(至少在msvc2005中),我想知道:正确的方法是什么?为什么它以其他方式编译呢?
我在开源项目X3C中读取了以下用于删除指针对象的代码.
//! Delete pointer object.
/*!
\ingroup _GROUP_UTILFUNC
\param p pointer object created using 'new'.
*/
template<class T>
void SafeDelete(T*& p)
{
if (p != NULL)
delete p;
p = NULL;
*(&p) = NULL;
}
Run Code Online (Sandbox Code Playgroud)
但我不知道这条线的意思:
*(&p) = NULL;
Run Code Online (Sandbox Code Playgroud)
在上面的行(p = NULL;)中,p被赋值为NULL.我认为它需要以另一种方式再次这样做.
假设我有一个带有两个指针的结构,每个指针指向一个具有已实现的析构函数的对象.还假设头指向Listnode结构,该结构具有非NULL值*student和*next:
struct Listnode {
Student *student;
Listnode *next;
};
Listnode *head = new Listnode;
Run Code Online (Sandbox Code Playgroud)
如果我使用deleteListnode指针'head'上的保留字,它将调用该结构中的析构函数Student class和Listnode类,其中'student'和'next'分别指向.换句话说,将删除*head也删除*student和*next提供的head是唯一指向该Listnode的指针
我需要一个C++复习.为什么这会给出内存异常?
pear = new char[1024];
pear = "happy go lucky";
delete [] pear; // exception
Run Code Online (Sandbox Code Playgroud) #include <new>
#include <cstdlib>
#include <iostream>
#include <stdexcept>
struct foo {};
inline void* operator new(size_t size, foo*) throw (std::bad_alloc)
{
std::cout << "my new " << size << std::endl;
return malloc(size);
}
inline void operator delete(void* p, foo*) throw()
{
std::cout << "my delete" << std::endl;
free(p);
}
int main()
{
delete new((foo*)NULL) foo;
}
Run Code Online (Sandbox Code Playgroud)
输出(通过ideone):
my new 1
Run Code Online (Sandbox Code Playgroud)
我的想法是,C++会释放一个带有附加参数的对象,并且匹配删除相同的参数,但我显然是不正确的.
获取上述代码调用重载删除的正确方法是什么?
只是一个简单的问题:
如果我没有实际为其分配新值,是否需要删除指针?
如果我创建了一个指针然后将其引用给了类似的东西,我做了什么:
Planet *planetPointer;
planetPointer = &earth;
Run Code Online (Sandbox Code Playgroud)
我是否需要删除此指针或者我可以将其设置为null?
当我在C++(T * p = new T[n])中分配动态数组时,我使用delete [] p释放分配的内存.显然,系统知道数组大小(按顺序调用n次T的析构函数).这在其他地方讨论过.例如,delete []"知道"操作数数组的大小是多少?.这是实施细节.
但为什么不决定提供这些信息呢?
谢谢
小心翼翼,这可能不太好.根据cppref:
如果expression是其他任何东西,包括它是否是由new-expression的数组形式获得的指针,则行为是未定义的.
把它放在一边,实际上是下面的代码OK(T非数组,假设new没有替换)?
auto p = (T*)operator new(sizeof(T));
new(p) T{};
delete p;
Run Code Online (Sandbox Code Playgroud)
据说在cppref中
当调用分配功能,新的表达通过请求作为第一个参数,类型的字节数
std::size_t,而这正是sizeof(T)对于非数组T.
所以我想这可能还行.但是,据说从C++ 14开始,
允许新表达式忽略或组合通过可替换分配函数进行的分配.在省略的情况下,存储器可以由编译器提供而不需要调用分配函数(这也允许优化掉未使用的new-expression).在组合的情况下,如果满足以下所有条件,则可以扩展由新表达式E1进行的分配以为另一个新表达式E2提供额外的存储:[...]
请注意,只有在使用new-expression时才允许此优化,而不是任何其他方法来调用可替换的分配函数:
delete[] new int[10];可以优化,但operator delete(operator new(10));不能.
我不太确定其含义.那么,这在C++ 14中可以吗?
我为什么问这个问题?(来源)
有时,内存分配和初始化无法在一个步骤中完成.您必须手动分配内存,执行其他操作,然后初始化对象,例如,以提供强大的异常安全性.在这种情况下,如果删除表达式无法在结果指针上使用,则必须手动取消初始化和取消分配,这很乏味.更糟糕的是,如果使用新表达式和手动方法,则必须跟踪每个对象使用哪一个.
c++ new-operator dynamic-memory-allocation delete-operator c++14
C++20 引入了“销毁运算符删除”的概念,如下所述:
在调用 operator delete 之前,delete-expressions 不会执行 *p 的析构函数
因此,鉴于以下情况struct S:
struct S {
void operator delete(S* p, std::destroying_delete_t);
private:
~S();
};
Run Code Online (Sandbox Code Playgroud)
我希望delete下面不会插入对析构函数的调用,而只是调用我们提供的销毁操作符 delete
delete new S;
Run Code Online (Sandbox Code Playgroud)
但是,GCC/Clang/MSVC 的行为有所不同:DEMO
只有 GCC 不会尝试访问~S(),其他人仍然需要~S()可访问。
哪一个是正确的?
c++ ×10
delete-operator ×10
new-operator ×3
pointers ×3
destructor ×2
arrays ×1
c++14 ×1
c++20 ×1
memory ×1
size ×1
struct ×1