C++ 运算符new()和运算符new[]()之间的区别?
FNC:新操作员和新操作员[](不是新操作员和新操作员[])之间是否有任何区别?当然除了调用语法?我这样问是因为我可以用::operator new(sizeof(T)*numberOfObject)为我的obj分配X个字节,然后用数组表示法访问它们,那么::operator new[]有什么大不了的呢。只是语法上的糖吗C++ 运算符new()和运算符new[]()之间的区别?,c++,memory,C++,Memory,FNC:新操作员和新操作员[](不是新操作员和新操作员[])之间是否有任何区别?当然除了调用语法?我这样问是因为我可以用::operator new(sizeof(T)*numberOfObject)为我的obj分配X个字节,然后用数组表示法访问它们,那么::operator new[]有什么大不了的呢。只是语法上的糖吗 #include <new> #include <iostream> #include <malloc.h> using namespac
#include <new>
#include <iostream>
#include <malloc.h>
using namespace std;
struct X
{
int data_;
X(int v):data_(v){}
};
int _tmain(int argc, _TCHAR* argv[])
{
unsigned no = 10;
void* vp = ::operator new(sizeof(X) * no);
cout << "Mem reserved: " << _msize(vp) << '\n';
X* xp = static_cast<X*>(vp);
for (unsigned i = 0; i < no; ++i)
{
new (xp + i) X(i);
}
for (unsigned i = 0; i < no; ++i)
{
cout << (xp[i]).data_ << '\n';
}
for (unsigned i = 0; i < no; ++i)
{
(xp + i)->~X();
}
::operator delete(vp);
return 0;
}
#包括
#包括
#包括
使用名称空间std;
结构X
{
int数据;
X(intv):数据_v{}
};
int _tmain(int argc,_TCHAR*argv[]
{
无符号编号=10;
void*vp=::运算符新(sizeof(X)*否);
cout函数的所需行为void*operator new(size\u t)
和void*operator new[](size\u t)
之间没有太大区别,只是它们与不同的释放函数配对
运算符本身是非常不同的。运算符之间的差异之一是使用了哪个分配函数,但最终还有许多其他差异,包括调用了多少构造函数等。但是您的示例代码没有使用运算符(好吧,它使用的是placement new)。您可能需要更改问题标题以明确这一点
从节[basic.stc.dynamic.deallocation]
:
如果解除分配函数终止
通过抛出异常,该行为
未定义。第一个
提供给解除分配的参数
函数可以是空指针值;
如果是,如果取消分配
函数是在
标准库,调用没有
效果。否则,值
提供给中的操作员删除(无效*)
标准库应为下列之一:
前一个函数返回的值
调用任一运算符
新(标准::尺寸)
或操作员
new(std::size\u t,const std::nothrow_-
t&)
在标准库中,以及
提供给运算符的值
删除标准中的[](无效*)
库应为其中一个值
由以前调用的返回
操作员新[](标准::大小\u t)
或
运算符新[](标准::大小,常数
标准中的std::nothrow\u t&
图书馆
分配是一回事,对象构建/销毁是另一回事。
new
执行一次分配和一次构造。然而,new[]
仍然分配一个连续内存块,但调用许多构造函数
delete
和delete[]
的情况相同
顺便说一句-我不是100%确定我要说的话,但我相信如果您对从new[]收到的地址调用delete
,您不会得到IMemidate内存泄漏
。整个内存块可能会被释放。但是,这是无效的,因为您只对第一个对象调用析构函数,而不是对数组中的每个对象调用析构函数。这可能会导致二次内存泄漏……当然,由于构造函数和析构函数的1-1关系被破坏,会导致许多逻辑错误
(也请记住使用<代码> Boo::<代码> STD::vector < <代码> new []/COD>!:):
< P>在您的示例代码中,您使用布局<代码> new <代码>来执行<代码>操作符new []/Cuffe自动执行的构造-与代码<新>不同将只执行默认构造,而您正在执行非默认放置构造 以下内容大致相当于您的示例:#include <iostream>
using namespace std;
struct X
{
int data_;
X(int v=0):data_(v){}
};
int main(int argc, char* argv[])
{
unsigned no = 10;
X* xp = new X[no];
for (unsigned i = 0; i < no; ++i) {
X tmp(i);
xp[i] = tmp;
}
for (unsigned i = 0; i < no; ++i)
{
cout << (xp[i]).data_ << '\n';
}
delete[] xp;
return 0;
}
#包括
使用名称空间std;
结构X
{
int数据;
X(intv=0):数据_v(v){
};
int main(int argc,char*argv[])
{
无符号编号=10;
X*xp=新X[否];
for(无符号i=0;ioperator new
等)通常不打算显式调用,而是由new
/new[]
表达式隐式使用(对称地,operator delete
/operator delete[]隐式调用delete
函数
expressions)。对非数组类型使用new
语法的表达式将隐式调用operator new
函数,而带有new[]
的表达式将隐式调用operator new[]
这里的重要细节是,由new[]
expression创建的数组通常稍后将由delete[]
expression销毁。后者需要知道要销毁的对象的数量(如果对象具有非平凡的析构函数),即必须以某种方式从new[]
expression传递此信息(已知时)对应的delete[]
表达式(需要时)。在典型实现中,此信息存储在new[]
表达式分配的块内,这就是对操作符new[]的隐式调用中请求的内存大小的原因
通常大于元素数量与元素大小的乘积。额外空间用于存储家庭信息(即元素数量)。稍后删除[]
expression将检索该家庭信息并使用它调用正确数量的析构函数,然后通过调用operator delete[]实际释放内存。
在您的示例中,您没有使用这些机制中的任何一种。在您的示例中,您显式调用内存分配函数,手动执行构造并完全忽略销毁步骤(这是可以的,因为您的对象具有普通的析构函数),这意味着至少出于销毁目的,您不需要跟踪数组中元素的确切数量。在任何情况下,您都可以跟踪该元素