delete的问题,和静态引用的问题 200分

就呆在云上 2008-10-07 04:26:25
一直回帖,不好意思了,今天就发一个帖,哈哈,说是高手进,也没有关系啦,只要说的好就给分!
还有我的结贴率超级高的,哈哈100%,
昨天写了一个类,出错了大概问题就是下面的代码的问题?
第一个为什么a要用后面的方法初始化,引用应该在在构造函数里面初始化,static应该在外面,莫非有“妥协”?:
class tt{
public:
int x;
static int &a;
tt() :x(10){}
};
int b = 10;
int &tt::a = b; 为什么这样初始化


第二个,先看代码?
	char *p = new char[10];
strcpy(p, "asdfasdfasdf");
delete []p;

我在几个群里面问了这个问题,都说越界了,大概就是说写越界了,我觉得跟他妈写越界有个鸡巴毛事情啊,写的时候不报错,却在delete的时候报错,因为我又写了两个相关的代码:
对数组写越界:
char p[10];
strcpy(p, "asdfasdfasdf");

系统自动释放p数组的时候也报错
但是,再看代码:
	char *p = new char[100];
char *pp = new(p) char[10];
strcpy(pp, "asdfasdfasdf");
delete []pp;

这样确不报错,我知道
delete []pp;
不好,但是同样是越界写了,为什么就不报错呢?
哎,分不多,就给200分吧。
...全文
568 77 打赏 收藏 转发到动态 举报
写回复
用AI写文章
77 条回复
切换为时间正序
请发表友善的回复…
发表回复
scarlettlee33 2011-08-31
  • 打赏
  • 举报
回复
真是经典,顶!!!!!
tkfly0324 2008-11-21
  • 打赏
  • 举报
回复
最后一个在vc里是编译不过去的
mifeixq 2008-10-13
  • 打赏
  • 举报
回复
mark
xmu_才盛 2008-10-08
  • 打赏
  • 举报
回复
先mark
我觉得delete在删除数组时是要看某个符号作为终结操作的,大概是/n或NULL吧
否则就会一直删下去,编译器肯定不允许这种危险操作的, 而且如果LZ是delete的作者在写这个函数时也会考虑到终止问题的吧

还有就是strcpy本来就是覆盖嘛,
地址 内容
0 a <----p
1 b
2 c
3 d
4 e
5 /n
执行 strcpy(p+1,p)
地址 内容
0 a <----p
1 a
2 b
3 c
4 d
5 e
6 /n
这个例子是说strcpy是内存的覆盖,根本不管是否越界
yshuise 2008-10-08
  • 打赏
  • 举报
回复
嗯,这是我第一次读标准。看来标准还是最全。
baihacker 2008-10-08
  • 打赏
  • 举报
回复
[Quote=引用 57 楼 yshuise 的回复:]
C/C++ code! new Tresults in a call ofoperator new(sizeof(T)),
! new(2,f) Tresults in a call ofoperator new(sizeof(T),2,f),
! new T[5]results in a call ofoperator new[](sizeof(T)*5+x), and
! new(2,f) T[5]results in a call ofoperator new[](sizeof(T)*5+y,2,f).
Here, x and y are non-negative unspecified values representing array allocation overhead; the result of th…
[/Quote]

你的解释:

这种解释仍然令人怀疑的。因为定位new只能把对象(构造函数)放到一个地址上。
而char[10]用法令人质疑。这种用法好像只有:new char[10],申请十个char空间,
先申请内存,后调用char的构造函数(这儿没有调)。而 new(p) char[10] 中,
定位new 能不能把char[10]识别成10个char的构造函数?所以错误才是对。我想只是编译器,或是
语法分析器没有识别到这个语言的角落,所以编译通过了。

在其中也回答了,这个解释是不对的.
jieao111 2008-10-08
  • 打赏
  • 举报
回复
没清楚lz的第二问题
K行天下 2008-10-08
  • 打赏
  • 举报
回复
问题比较好

觉得主要是覆盖了new分配内存的结构,堆中的内存结构每个块前面都有这个块是否空闲以及大小的标记,这样释放的时候便于管理
yshuise 2008-10-08
  • 打赏
  • 举报
回复
! new Tresults in a call ofoperator new(sizeof(T)),
! new(2,f) Tresults in a call ofoperator new(sizeof(T),2,f),
! new T[5]results in a call ofoperator new[](sizeof(T)*5+x), and
! new(2,f) T[5]results in a call ofoperator new[](sizeof(T)*5+y,2,f).
Here, x and y are non-negative unspecified values representing array allocation overhead; the result of the
new-expression will be offset by this amount from the value returned by operator new[]. This over-
head may be applied in all array new-expressions, including those referencing the library function
operator new[](std::size_t, void*) and other placement allocation functions. The amount
of overhead may vary from one invocation ofnewto another. ]

从标准来看,第二个问题上面实际上有人已经回答了。
编译器会自己指定一个额外的空间存放new的信息,又叫cookies。
而越界的使用很可能把cookies覆盖了,所以delete根本找不到这个cookies,就错了。
e_sharp 2008-10-08
  • 打赏
  • 举报
回复
UP
yshuise 2008-10-08
  • 打赏
  • 举报
回复
我下个标准看看
frank_ll 2008-10-08
  • 打赏
  • 举报
回复
class tt{
public:
int x;
static int &a;
tt() :x(10){}
};
int b = 10;
int &tt::a = b; 为什么这样初始化
//static 必须在外面初始化


后面的指针问题是

char *p = new char[100];//预先分配了100字节的空间
char *pp = new(p) char[10];//在100字节已分配空间上写是不会出现问题的
strcpy(pp, "asdfasdfasdf");
delete []pp;
baihacker 2008-10-08
  • 打赏
  • 举报
回复
to49楼,请看标准:
11 The new-placement syntax is used to supply additional arguments to an allocation function. If used, over-
load resolution is performed on a function call created by assembling an argument list consisting of the
amount of space requested (the first argument) and the expressions in the new-placement part of the new-
expression (the second and succeeding arguments). The first of these arguments has type size_t and the
remaining arguments have the corresponding types of the expressions in thenew-placement.
12 [Example:
! new Tresults in a call ofoperator new(sizeof(T)),
! new(2,f) Tresults in a call ofoperator new(sizeof(T),2,f),
! new T[5]results in a call ofoperator new[](sizeof(T)*5+x), and
! new(2,f) T[5]results in a call ofoperator new[](sizeof(T)*5+y,2,f).
Here, x and y are non-negative unspecified values representing array allocation overhead; the result of the
new-expression will be offset by this amount from the value returned by operator new[]. This over-
head may be applied in all array new-expressions, including those referencing the library function
operator new[](std::size_t, void*) and other placement allocation functions. The amount
of overhead may vary from one invocation ofnewto another. ]



15 Anew-expressionthat creates an object of typeTinitializes that object as follows:
!a If thnew-initializer is omitted:
!a I T is a (possibly cv-qualified) non-POD class type (or array thereof), the object is default-
initialized (8.5). If T is a const-qualified type, the underlying class type shall have a user-declared
default constructor.
!a Otherwise, the object created has indeterminate value. I T is a const-qualified type, or a (possibly
cv-qualified) POD class type (or array thereof) containing (directly or indirectly) a member of
const-qualified type, the program is ill-formed;
!a If thnew-initializer is of the form(), the item is value-initialized (8.5);
!a If th new-initializer is of the form (expression-list) and T is a class type, the appropriate constructor is
called, usingexpression-listas the arguments (8.5);
!a If th new-initializer is of the form (expression-list) and T is an arithmetic, enumeration, pointer, or
pointer-to-member type and expression-list comprises exactly one expression, then the object is initial-
ized to the (possibly converted) value of the expression (8.5);
!a Otherwise thnew-expressionis ill-formed.



1 The new-expression attempts to create an object of the type-id (8.1) or new-type-id to which it is applied.
The type of that object is the allocated type. This type shall be a complete object type, but not an abstract
class type or array thereof (1.8, 3.9, 10.4). [Note: because references are not objects, references cannot be
created by new-expressions. ] [Note: the type-id may be a cv-qualified type, in which case the object cre-
ated by thenew-expressionhas a cv-qualified type. ]
new-expression:
new new-placement new-type-id new-initializer
::
opt opt opt
:: new new-placement ( type-id ) new-initializer
opt opt opt
new-placement:
( expression-list )
new-type-id:
type-specifier-seq new-declarator
opt
new-declarator:
ptr-operator new-declarator
opt
direct-new-declarator
direct-new-declarator:
[ expression ]
direct-new-declarator [ constant-expression ]
new-initializer:
)
( expression-list
opt
Entities created by a new-expression have dynamic storage duration (3.7.3). [Note: the lifetime of such an
entity is not necessarily restricted to the scope in which it is created. ] If the entity is a non-array object, the
new-expressionreturns a pointer to the object created. If it is an array, the new-expression returns a pointer
to the initial element of the array.
wqzh_wzhy 2008-10-08
  • 打赏
  • 举报
回复
受益非浅啊!!! 学习!
wqzh_wzhy 2008-10-08
  • 打赏
  • 举报
回复
受益非浅啊!!! 学习!
yshuise 2008-10-08
  • 打赏
  • 举报
回复
另外这些问题也不是什么好高深的问题,只是没有遵守语法规则倒腾出来,浪费时间的产物。
yshuise 2008-10-08
  • 打赏
  • 举报
回复
[Quote=引用 31 楼 baihacker 的回复:]
在这里char* pp = new(p) char[10];和
char pp = p;等价,一个伪装骗了很多人了.

什么时候不等价呢?
一个放置,如果是分配一个数组的话,会为这些对象调用一次默认构造函数,这个时候不等价.
如果是基本类型,就没有这个过程,也不能为每个对象指派一个初值,所以等价
如果是分配一个对象
A* pp = new(p) A(参数);
那么这里也不等价,A是一个类的时候有构造函数的调用,A是基本类型的时候会有一个初始化的过程,所以不等价
如果你啥都不做,当然等价了.

[/Quote]
这种解释仍然令人怀疑的。因为定位new只能把对象(构造函数)放到一个地址上。
而char[10]用法令人质疑。这种用法好像只有:new char[10],申请十个char空间,
先申请内存,后调用char的构造函数(这儿没有调)。而 new(p) char[10] 中,
定位new 能不能把char[10]识别成10个char的构造函数?所以错误才是对。我想只是编译器,或是
语法分析器没有识别到这个语言的角落,所以编译通过了。
yuzl32 2008-10-08
  • 打赏
  • 举报
回复
^o^
yuzl32 2008-10-08
  • 打赏
  • 举报
回复
^o^
littlechen 2008-10-08
  • 打赏
  • 举报
回复
想这些问题干吗,按照规范来写代码就可以了。
设计并实现C语言编译器的人看到这些问题会是如何想法?
加载更多回复(57)

64,646

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧