为什么goto不能跳过初始化操作?

C++语言 码拜 10年前 (2015-05-11) 5311次浏览 0个评论
 

……
goto test;
int i;
string str;
test:
{
……
}
……
为什么这里通不过编译呢?把string str;这一句拿到goto之前就可以了?
为什么后面的int i;这一句不需要拿到goto之前呢?

5分
依据我的判断应该是内存的事,函数和 int i;变量都是在栈上的,而且i所占内存大小是固定的,而string是动态内存分配,在堆上的,大小可变。
10分
具体内部原因不知道,也待答案

1.在c++ Primer中倒是提到,goto 不能向前跳过变量定义语句,给出的理由是可能引起未定义的变量使用。当确实要这样使用时,需要把定义语句使用{}括起来。

但是奇怪在vs中,确实只需要注释 string 定义的一句就可以执行。
但是在g++中,定义i的同时赋值(int i=10;),则会提示出错,但是如果只声明i,在声明后赋值或者不赋值(int i; i=10),都不报错。

因为“规定”
引用 3 楼 taodm 的回复:

因为“规定”

呵呵
王八的屁股

5分
引用 楼主 yujiefei0309 的回复:

……
goto test;
int i;
string str;
test:
{
……
}
……
为什么这里通不过编译呢?把string str;这一句拿到goto之前就可以了?
为什么后面的int i;这一句不需要拿到goto之前呢?

6.7 Declaration statement

………….A program that jumps from a point where a local variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has POD type (3.9) and is declared without an initializer (8.5).

就是说,当跳过自动局部变量时,只能跳过未初始化的POD变量,其余情况都属于错误的代码结构。

因为这样只有析构,没有构造了。
引用 6 楼 Saleayas 的回复:

因为这样只有析构,没有构造了。

不懂啊。。。

引用 7 楼 yujiefei0309 的回复:

引用 6 楼 Saleayas 的回复:因为这样只有析构,没有构造了。不懂啊。。。

这个不懂得话,那么就别用goto了。

引用 8 楼 akirya 的回复:

引用 7 楼 yujiefei0309 的回复:
引用 6 楼 Saleayas 的回复:因为这样只有析构,没有构造了。不懂啊。。。
这个不懂得话,那么就别用goto了。

但是我goto跳过后面的string str;之后,跳转到的语句并没有使用str这个变量啊,也会对str析构吗?

因为堆栈需要知道分配的大小
引用 9 楼 yujiefei0309 的回复:

引用 8 楼 akirya 的回复:引用 7 楼 yujiefei0309 的回复:
引用 6 楼 Saleayas 的回复:因为这样只有析构,没有构造了。不懂啊。。。
这个不懂得话,那么就别用goto了。但是我goto跳过后面的string str;之后,跳转到的语句并没有使用str这个变量啊,也会对str析构吗?

str那部分代码外加个大括号

对学习编程者的忠告:
眼过千遍不如手过一遍!
书看千行不如手敲一行!
手敲千行不如单步一行!
单步源代码千行不如单步对应汇编一行!

单步类的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代码几步后,就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。

VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。

应该是在编译的时候编译器就已经检查过了吧,如果一句goto可以跳过变量声明,后面那些“没声明”的变量要怎么处理?
因为string是类类型,而int是变量。变量在局部是不默认初始化的,而string是会隐形初始化的。c++ primer中讲到,string对象不初始化,它会默认初始化为空串。
而c++语言规定,不允许跨过变量的初始化语句直接跳转到该变量作用域内的另一个位置。
string对象隐形初始化了,而int变量只是定义,没有初始化,这就是为什么注释掉string后能成功运行了
据我推断,基本类型如int这种,在栈中是被默认初始化的。而对象如string这种,是需要在运行时执行构造函数的,如果goto跳过string的定义,那string的构造函数就得不到执行,那么string占用的栈空间就会处于未初始化状态,可能C++认为这会导致风险,所以就禁止了这种情形的发生。

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明为什么goto不能跳过初始化操作?
喜欢 (0)
[1034331897@qq.com]
分享 (0)

文章评论已关闭!