在我的C++程序中,我使用new在一个函数中创建对象.这些对象被插入到一个集合中.当我想从集合中删除对象时,我在for循环中使用了一个迭代器.当我从集合中删除对象时,我仍然需要删除该对象以释放其内存,对吗?我尝试使用删除,但后来我得到一个错误,说没有分配被释放的指针.那么怎么做呢?
这是我创建对象然后将其插入集合的代码
set <myObject> myobjectlist;
myObject *myobject = new myObject;
myobjectlist.insert(*myobject);
Run Code Online (Sandbox Code Playgroud)
在另一个函数中,我尝试从集合中删除一个对象,并释放它的内存:
for (set<myObject>::iterator i = myobjectlist.begin(); i != myobjectlist.end(); i++)
if (i->myObjectID == myObjectID)
{
myobjectlist.erase(*i);
delete &i;
break;
}
Run Code Online (Sandbox Code Playgroud)
这没有"删除"部分工作正常.我添加它是因为我认为来自对象的内存没有被释放.
所以我习惯于在C中进行内存管理,这free(pointer)将释放所有指向的空间pointer.现在,当我尝试用C++做一些简单的事情时,我会感到困惑.
如果我有一个二维数组的双精度分配方式与此类似
double** atoms = new double*[1000];
for(int i = 0; i < 1000; i++)
atoms[i] = new double[4];
Run Code Online (Sandbox Code Playgroud)
什么是释放新分配的堆上的内存的正确方法?
我的想法原来是这样的(因为我的大脑在用C思考):
for(int i = 0; i < 1000; i++)
delete atoms[i];
delete atoms;
Run Code Online (Sandbox Code Playgroud)
但是我忘记了delete[]运算符的存在,所以我相信正确的方法如下:
for(int i = 0; i < 1000; i++)
delete[] atoms[i];
delete[] atoms;
Run Code Online (Sandbox Code Playgroud)
理解delete和delete[]运营商之间的区别是否重要?或者我可以假设每当我分配一个数组时,ptr = new x[]我还必须解除分配delete[] ptr?
以下类(带有虚拟析构函数)包含模板化的operator delete:
struct S\n{\n virtual ~S() {}\n template <typename... Args>\n void operator delete(void* ptr, Args... args);\n};\nRun Code Online (Sandbox Code Playgroud)\nargs可以为空,所以我认为S::operator delete也可以在预期常规时使用delete。
但是(使用 g++),我收到错误\xef\xbc\x9a
\n\n\n错误:“S”没有合适的“操作符删除”
\n
难道“合适的‘操作删除’”就不能成为一个模板吗?
\n我编写了一个程序来分配类T的新对象,如下所示:
T* obj = new T(tid);
Run Code Online (Sandbox Code Playgroud)
其中tid是一个int
在我的代码中的其他地方,我正在尝试释放我已分配的对象,它位于向量内,使用:
delete(myVec[i]);
Run Code Online (Sandbox Code Playgroud)
然后:
myVec[i] = NULL;
Run Code Online (Sandbox Code Playgroud)
有时它会通过而没有任何错误,并且在某些情况下会导致崩溃 - 分段错误.
我在调用delete之前已经检查过,那个对象就在那里 - 我以前没有删除它.
什么可能导致这次崩溃?
这是我将类型T的对象插入向量的代码:
_myVec is global
int add() {
int tid = _myVec.size();
T* newT = new T (tid);
if (newT == NULL){
return ERR_CODE;
}
_myVec.push_back(newT);
// _myVec.push_back(new T (tid));
return tid;
}
Run Code Online (Sandbox Code Playgroud)
事实上 - 程序有时会崩溃.
当我用注释行替换push_back行,并保持原样 - 它工作.
但当我用以下代码替换此代码时:
int add() {
int tid = _myVec.size();
if (newT == NULL){
return ERR_CODE;
}
_myVec.push_back(new T (tid));
return tid;
}
Run Code Online (Sandbox Code Playgroud)
它在不同的阶段崩溃了...... …
我正在尝试(并已解决)包含SSE优化成员的类的16字节对齐问题.但令我烦恼的是,我在网上找到的大部分例子都包含一行代码,对我来说似乎完全是多余的,但在很多地方都会重复.
public:
void* operator new (size_t size)throw (std::bad_alloc)
{
void * p = _aligned_malloc(size, 16);
if (p == 0) throw std::bad_alloc();
return p;
}
void operator delete (void *p)
{
Camera* pC = static_cast<Camera*>(p);
_aligned_free(p);
}
Run Code Online (Sandbox Code Playgroud)
这条线是
Camera* pC = static_cast<Camera*>(p);
Run Code Online (Sandbox Code Playgroud)
由于pC从未被引用并且在函数结束时超出范围,所以有什么意义呢?我试过把这条线拿出去,它似乎完全没有区别,但这一行出现在很多例子中!我是否遗漏了一些非常明显的东西,或者有一些异常的代码被盲目地从一个例子复制到另一个例子并在很多"教程"中变得流行?
假设我想制作一个无法构造的类型(不要问为什么).
struct Impossible
{
Run Code Online (Sandbox Code Playgroud)
我可以这样做:
Impossible() = delete;
// disable automatically generated constructors, don't declare any others
Impossible(const Impossible&) = delete;
// I suppose this is redundant with nothing to copy
Run Code Online (Sandbox Code Playgroud)
或者像这样:
Impossible(...) = delete;
// explicitly disable all constructors
Run Code Online (Sandbox Code Playgroud)
或者像这样:
template<typename... Ts>
Impossible(Ts...) = delete;
// explicitly disable all constructors, template version
};
Run Code Online (Sandbox Code Playgroud)
我想我可以对任何函数提出同样的问题,而不仅仅是构造函数.
我选择哪一个有什么不同?在语法方面,我认为我喜欢第二种选择.但是,在任何情况下,是否有可能检测到差异(除了错误信息的文本中)?
用于删除和我们使用的元素数组delete[].是否可以按照我在下面的方式删除指针?
ClassA* object = new ClassA();
ClassA* pointer1 = object;
ClassA* object2 = new ClassA();
ClassA* pointer2 = object2;
delete pointer1,pointer2;
Run Code Online (Sandbox Code Playgroud)
为什么不能用这种方式删除?
[编辑]
我可以说,有什么缺点导致上述删除没有实现?
C++ Reference页面列出了全局新运算符的 8个特定于类的重载.其中四个是为2017版C++添加的.
特定于类的分配函数
void* T::operator new ( std::size_t count );
void* T::operator new[]( std::size_t count );
void* T::operator new ( std::size_t count, std::align_val_t al ); // (since C++17)
void* T::operator new[]( std::size_t count, std::align_val_t al ); // (since C++17)
Run Code Online (Sandbox Code Playgroud)
特定于类的放置分配功能
void* T::operator new ( std::size_t count, user-defined-args... );
void* T::operator new[]( std::size_t count, user-defined-args... );
void* T::operator new ( std::size_t count,
std::align_val_t al, user-defined-args... ); // (since C++17)
void* T::operator new[]( std::size_t count,
std::align_val_t …Run Code Online (Sandbox Code Playgroud) 我已经写了下面的代码,重载new及delete运营商,并引发在析构函数的异常.
抛出异常时,为什么delete操作符中的代码没有执行(并且"再见"打印)?
如果不应该执行,(如何)释放内存?是其他delete运营商之一吗?是否会重载其中一个而导致执行相应的代码?或者内存根本没有被释放,因为破坏失败意味着它可能不应该是?
#include <iostream>
using namespace std;
class A
{
public:
A() { }
~A() noexcept(false) { throw exception(); }
void* operator new (std::size_t count)
{
cout << "hi" << endl;
return ::operator new(count);
}
void operator delete (void* ptr)
{
cout << "bye" << endl;
return ::operator delete(ptr);
}
// using these (with corresponding new's) don't seem to work either
// void operator delete (void* ptr, const std::nothrow_t& …Run Code Online (Sandbox Code Playgroud) 我正在阅读关于SO的问题,在其中一个答案中,它被提到:
如果找不到明确的匹配解除分配函数,则传播异常不会导致释放对象的内存.
所以,如果我只是重载我的new运算符而不是delete运算符,那么是否delete会创建并调用任何默认运算符; 或者,我是否还必须delete明确地编写运算符.
c++ ×10
delete-operator ×10
c++11 ×2
new-operator ×2
pointers ×2
destructor ×1
exception ×1
memory ×1
object ×1
replace ×1
static-cast ×1