C++weblogic激活更改报错不会改

当前位置>>>
偶然碰到一个问题,电脑在开机之后,提示一个vc++ runtime错误,导致电脑无法进入桌面,至于使用更是没有办法了,情况如下!一般碰这样的错误都是因为电脑开机之后运行了某个任务,导致系统错误无法进入桌面,我们可以尝试重建explorer,看能否进入桌面,如果能够进入,找到对应的程序错误就可以按照报错位置,找到对应的程序,将报错程序卸载。如果不行,我们还可以运行msconfig命令,直接将有关开始程序禁用比如上图出现错误的是一个虚拟光驱的程序,我们直接禁用就可以了!当然最后,如果还是进入不了,我们就需要尝试更改注册表了!同样在任务管理器中输入regedit打开注册表,打开之后,我们按f3弹出搜索框,我们输入run,勾选项匹配,勾选全字匹配,点击确定之后开始搜索。只要弹出的项中含有runtime键值我们一律删除,当然如果没有搜索到,我们可以再次按f3往下继续搜索,知道搜索到为止!最后如果大家还有什么意见或者建议,请到u大师官网留言 ,或者到u大师论坛留言,也可以直接联系客服,祝生活愉快!
少侠请留名问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
源代码很简单,就是定义一个float变量a=2.5,int变量b=2
然后将a,b分别按%d %f型输出。
当然没有按正确类型格式化输出肯定是有问题的。
但是按正确类型格式化输出也发生了很奇怪的问题。
源代码如下,VS2013下编译通过0 errors, 0 warnings。
#include &stdio.h&
int main(void)
float a = 2.5;
int b = 2;
printf("%d\n%f\n%d\n%f\n", a, a, b, b);
/*这条语句的输出全是错的*/
putchar('\n');
printf("%f\n%d\n%f\n%d\n", a, a, b, b);
/*这条语句的输出有两个对的两个错的,符合我的预期*/
return(0);}
输出结果如下图
我的主要问题是,为什么第一个printf的输出没有一个是对的?
本人是小白,希望能有大神帮忙解答,多谢!
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
首先,float在这里会自动转换为double, 为了方便理解,我们在这里假设 sizeof(int) 是 4, sizeof(double) 是 8.
然后,针对这一句:
printf("%d\n%f\n%d\n%f\n", a, a, b, b);
依照 %d\n%f\n%d\n%f 去读,栈里面的数据以及读取的指针将呈现如下形式:
(float)a_&|
(int)b_&|_2.5_|4
(float)b_&|__2__|4
所以呢,第一个 %d 读到的实际是 2.5 的前 4 byte。 紧接着第一个 %f 读的是 2.5 的后 4 byte, 加上下一个 2.5 的前 4 byte. 同理,第二个 %d 读到的是 2.5 的后 4 byte, 而第二个 %f 读到的是两个 2.
好吧,是不是有点乱。C 语言中是如何定义这种在输出里"类型乱读"的现象呢?
7.21.6 Formatted input/output functions:
If a conversion specification is invalid, the behavior is undefined.282) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
如标准所言,这是 UB (未定义行为),所以至于它为何会输出你截图里的那四个数,可以不必深究。不同编译器的结果也不尽相同。
上面分析了原理,那么也可以顺带分析一下你的第二句为什么可以输出你想要的。
依照 %f\n%d\n%f\n%d 去读,栈里面的数据以及读取的指针将呈现如下形式:
(float)a_&|_2.5_|4_ _ _ _ _ _ correct!
(float)b_&|__2__|4
(int)b_&|__2__|4_ _ _ _ _ _ correct!
运气不错,牛头正好对上了马嘴,你得到了你想要的输出。。。
不要侥幸,老老实实的按类型去 printf, 才是初学者正确的态度。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
你留意一下标准库里面的stdarg.h文件,它里面定义了几个宏,分别是va_start、va_arg、va_end,这几个宏都是用来做不定参数传递的。特别注意的是va_arg在获取传递进来的参数时依赖它的第二个参数(t,类型),如果类型不对应的话会导致整个不定参数的传递没法正常的解析(错位)。prinft依赖于vsprintf,而vsprintf的实现依赖这几个宏,它会根据格式字符串(也就是那些%d %f ...)来调用va_arg,如果你的格式字符串和你后面的不定参数没有正确对应起来,那么也有可能在获取不定参数时出现错位(而你第二个输出对了两次也是因为错位了两次之后刚好又对上了的缘故)。
还有float(32位)参数在传递printf的时候会自动转换成double(64位)(这也是%f和%lf没区别的缘故),int参数占32位。
有了上面的铺垫之后,下面来解释你的这个问题。
环境:Windows XP 32, gcc version 3.4.0 (mingw special)
注:以下连续的十六进制数据从左到右对应于内存地址的由低到高
你传入的参数a,a,b,b,对应十六进制的00 00 00 00 00 00 04 40 00 00 00 00 00 00 04 40 02 00 00 00 02 00 00 00正确的分割应该是:
a: [00 00 00 00 00 00 04 40]
a: [00 00 00 00 00 00 04 40]
b: [02 00 00 00]
b: [02 00 00 00]
根据你的第一次输出的格式字符串,printf做了如下的分割:
%d: [00 00 00 00] int,对应0x,也就是0了
%f: [00 00 04 40 00 00 00 00] double,0.0,(看double的表示法)
%d: [00 00 04 40] int,对应0x,也就是10进制的
%f: [02 00 00 00 02 00 00 00] double,0.0
所以输出也就是:
而根据你第二次输出的格式字符串,printf做了如下的分割:
%f: [00 00 00 00 00 00 04 40] double, 对应2.5
%d: [00 00 00 00] int 对应0
%f: [00 00 04 40 02 00 00 00]
double,对应0
%d:[02 00 00 00] int 对应0
也就是你看到的:
至于为什么好几次double都变成0.0,你需要去看看IEEE的double表示标准。
简而言之就是:printf的在做输出的时候会根据格式字符串来获取传递进来的不定参数,而错误的格式字符串会导致不定参数的获取错误,从而导致输出错误。
同步到新浪微博
分享到微博?
你好!看起来你挺喜欢这个内容,但是你还没有注册帐号。 当你创建了帐号,我们能准确地追踪你关注的问题,在有新答案或内容的时候收到网页和邮件通知。还能直接向作者咨询更多细节。如果上面的内容有帮助,记得点赞 (????)? 表示感谢。
明天提醒我
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:中国领先的IT技术网站
51CTO旗下网站
深入理解C++中的异常处理机制
例子看起来还是比较简单的,但是用处还是很大的,对于赋值操作符来说,很多情况都是需要重载的.
作者:来源:| 11:25
增强错误恢复能力是提高代码健壮性的最有力的途径之一,C语言中采用的错误处理方法被认为是紧耦合的,函数的使用者必须在非常靠近函数调用的地方编 写错误处理代码,这样会使得其变得笨拙和难以使用。C++中引入了异常处理机制,这是C++的主要特征之一,是考虑问题和处理错误的一种更好的方式。使用 错误处理可以带来一些优点,如下:
错误处理代码的编写不再冗长乏味,并且不再和正常的代码混合在一起,只需要编写希望产生的代码,然后在后面某个单独的区段里编写处理错误的嗲吗。多次调用同一个函数,则只需要某个地方编写一次错误处理代码。
错误不能被忽略,如果一个函数必须向调用者发送一次错误信息。它将抛出一个描述这个错误的对象。
传统的错误处理和异常处理
在讨论异常处理之前,我们先谈谈C语言中的传统错误处理方法,这里列举了如下三种:
在函数中返回错误,函数会设置一个全局的错误状态标志。
使用信号来做信号处理系统,在函数中raise信号,通过signal来设置信号处理函数,这种方式耦合度非常高,而且不同的库产生的信号值可能会发生冲突
使用标准C库中的非局部跳转函数 setjmp和longjmp ,这里使用setjmp和longjmp来演示下如何进行错误处理:
#include&&iostream&&#include&&setjmp.h&&jmp_buf&static_&&&void&do_jmp()&{&&&&&&&&&&&&&&&longjmp(static_buf,10);&}&&int&main()&{&&&&&int&ret&=&0;&&&&&&&&&&if((ret&=&setjmp(static_buf))&==&0)&{&&&&&&&&&&&&&&&&&&do_jmp();&&&&&}&else&{&&&&&&&&&&&&&if&(ret&==&10)&&&&&&&&&&&&&std::cout&&&&&a&little&error&&&&&std::&&&&&}&}&
错误处理方式看起来耦合度不是很高,正常代码和错误处理的代码分离了,处理处理的代码都汇聚在一起了。但是基于这种局部跳转的方式来处理代码,在 C++中却存在很严重的问题,那就是对象不能被析构,局部跳转后不会主动去调用已经实例化对象的析构函数。这将导致内存泄露的问题。下面这个例子充分显示 了这点
#include&&iostream&&#include&&csetjmp&&&using&namespace&&&class&base&{&&&&&public:&&&&&&&&&base()&{&&&&&&&&&&&&&cout&&&&&base&construct&func&call&&&&&&&&&&&&&&}&&&&&&&&&~base()&{&&&&&&&&&&&&&cout&&&&&~base&destruct&func&call&&&&&&&&&&&&&&}&};&&jmp_buf&static_&&void&test_base()&{&&&&&base&b;&&&&&&&&&&longjmp(static_buf,47);&}&&int&main()&{&&&&&if(setjmp(static_buf)&==&0)&{&&&&&&&&&cout&&&&&deal&with&some&thing&&&&&&&&&&&&&&test_base();&&&&&}&else&{&&&&&&&&&cout&&&&&catch&a&error&&&&&&&&&&}&}&
在上面这段代码中,只有base类的构造函数会被调用,当longjmp发生了跳转后,b这个实例将不会被析构掉,但是执行流已经无法回到这里,b 这个实例将不会被析构。这就是局部跳转用在C++中来处理错误的时候带来的一些问题,在C++中异常则不会有这些问题的存在。那么接下来看看如何定义一个 异常,以及如何抛出一个异常和捕获异常吧.
异常的抛出
class&MyError&{&&&&&const&char*&const&&public:&&&&&MyError(const&char*&const&msg&=&0):data(msg)&&&&&{&&&&&&&&&&&&&&}&};&&void&do_error()&{&&&&&throw&MyError(&something&bad&happend&);&}&&int&main()&{&&&&&do_error();&}&
上面的例子中,通过throw抛出了一个异常类的实例,这个异常类,可以是任何一个自定义的类,通过实例化传入的参数可以表明发生的错误信息。其实 异常就是一个带有异常信息的类而已。异常被抛出后,需要被捕获,从而可以从错误中进行恢复,那么接下来看看如何去捕获一个异常吧。在上面这个例子中使用抛 出异常的方式来进行错误处理相比与之前使用局部跳转的实现来说,最大的不同之处就是异常抛出的代码块中,对象会被析构,称之为堆栈反解.
异常的捕获
C++中通过catch关键字来捕获异常,捕获异常后可以对异常进行处理,这个处理的语句块称为异常处理器。下面是一个简单的捕获异常的例子:
try{&&&&&&&&&&throw&string(&this&is&exception&);&}&catch(const&string&&e)&{&&&&&cout&&&&&catch&a&exception&&&&&&e&&&&&}&
catch有点像函数,可以有一个参数,throw抛出的异常对象,将会作为参数传递给匹配到到catch,然后进入异常处理器,上面的代码仅仅是 展示了抛出一种异常的情况,加入try语句块中有可能会抛出多种异常的,那么该如何处理呢,这里是可以接多个catch语句块的,这将导致引入另外一个问 题,那就是如何进行匹配。
异常的匹配
异常的匹配我认为是符合函数参数匹配的原则的,但是又有些不同,函数匹配的时候存在类型转换,但是异常则不然,在匹配过程中不会做类型的转换,下面的例子说明了这个事实:
#include&&iostream&&&using&namespace&&int&main()&{&&&&&try{&&&&&&&&&&throw&'a';&&&&&}catch(int&a)&{&&&&&&&&&cout&&&&&int&&&&&&&&&&}catch(char&c)&{&&&&&&&&&cout&&&&&char&&&&&&&&&&}&}&
上面的代码的输出结果是char,因为抛出的异常类型就是char,所以就匹配到了第二个异常处理器。可以发现在匹配过程中没有发生类型的转换。将 char转换为int。尽管异常处理器不做类型转换,但是基类可以匹配到派生类这个在函数和异常匹配中都是有效的,但是需要注意catch的形参需要是引 用类型或者是指针类型,否则会&导致切割派生类这个问题。
&class&Base{&&&&&public:&&&&&&&&&Base(string&msg):m_msg(msg)&&&&&&&&&{&&&&&&&&&}&&&&&&&&&virtual&void&what(){&&&&&&&&&&&&&cout&&&&m_msg&&&&&&&&&&&&&}&&&&&void&test()&&&&&{&&&&&&&&&cout&&&&&I&am&a&CBase&&&&&&&&&&}&&&&&protected:&&&&&&&&&string&m_&};&&class&CBase&:&public&Base&{&&&&&public:&&&&&&&&&CBase(string&msg):Base(msg)&&&&&&&&&{&&&&&&&&&&}&&&&&&&&&void&what()&&&&&&&&&{&&&&&&&&&&&&cout&&&&&CBase:&&&&&m_msg&&&&&&&&&&&&&}&};&&int&main()&{&&&&&try&{&&&&&&&&&&&&&&&&&&&&&&&throw&CBase(&I&am&a&CBase&exception&);&&&&&&}catch(Base&&e)&{&&&&&&&&&&&e.what();&&&&&}&}&
上面的这段代码可以正常的工作,实际上我们日常编写自己的异常处理函数的时候也是通过继承标准异常来实现字节的自定义异常的,但是如果将 Base&换成Base的话,将会导致对象被切割,例如下面这段代码将会编译出错,因为CBase被切割了,导致CBase中的test函数无法 被调用。
try&{&&&&&&&&&&throw&CBase(&I&am&a&CBase&exception&);&&}catch(Base&e)&{&&&&&e.test();&}&
到此为此,异常的匹配算是说清楚了,总结一下,异常匹配的时候基本上遵循下面几条规则:
异常匹配除了必须要是严格的类型匹配外,还支持下面几个类型转换.
允许非常量到常量的类型转换,也就是说可以抛出一个非常量类型,然后使用catch捕捉对应的常量类型版本
允许从派生类到基类的类型转换
允许数组被转换为数组指针,允许函数被转换为函数指针
假想一种情况,当我要实现一代代码的时候,希望无论抛出什么类型的异常我都可以捕捉到,目前来说我们只能写上一大堆的catch语句捕获所有可能在 代码中出现的异常来解决这个问题,很显然这样处理起来太过繁琐,幸好C++提供了一种可以捕捉任何异常的机制,可以使用下列代码中的语法。
catch(...) {
&&& //异常处理器,这里可以捕捉任何异常,带来的问题就是无法或者异常信息
如果你要实现一个函数库,你捕捉了你的函数库中的一些异常,但是你只是记录日志,并不去处理这些异常,处理异常的事情会交给上层调用的代码来处理.对于这样的一个场景C++也提供了支持.
try{&&&&&throw&Exception(&I&am&a&exception&);&&&&}catch(...)&{&&&&&&&&&&throw;&}&
通过在catch语句块中加入一个throw,就可以把当前捕获到的异常重新抛出.在异常抛出的那一节中,我在代码中抛出了一个异常,但是我没有使用任何catch语句来捕获我抛出的这个异常,执行上面的程序会出现下面的结果.
terminate&called&after&throwing&an&instance&of&'MyError'&Aborted&(core&dumped)&
为什么会出现这样的结果呢?,当我们抛出一个异常的时候,异常会随着函数调用关系,一级一级向上抛出,直到被捕获才会停止,如果最终没有被捕获将会 导致调用terminate函数,上面的输出就是自动调用terminate函数导致的,为了保证更大的灵活性,C++提供了set_terminate 函数可以用来设置自己的terminate函数.设置完成后,抛出的异常如果没有被捕获就会被自定义的terminate函数进行处理.下面是一个使用的 例子:
#include&&exception&&#include&&iostream&&#include&&cstdlib&&using&namespace&&&class&MyError&{&&&&&const&char*&const&&public:&&&&&MyError(const&char*&const&msg&=&0):data(msg)&&&&&{&&&&&&&&&&&&&&}&};&&void&do_error()&{&&&&&throw&MyError(&something&bad&happend&);&}&&void&terminator()&{&&&&&cout&&&&&I'll&be&back&&&&&&&&&&exit(0);&}&&int&main()&{&&&&&&&&&&void&(*old_terminate)()&=&set_terminate(terminator);&&&&&do_error();&}&上面的代码会输出I'll&be&back&
到此为此关于异常匹配的我所知道的知识点都已经介绍完毕了,那么接着可以看看下一个话题,异常中的资源清理.
异常中的资源清理
在谈到局部跳转的时候,说到局部调转不会调用对象的析构函数,会导致内存泄露的问题,C++中的异常则不会有这个问题,C++中通过堆栈反解将已经 定义的对象进行析构,但是有一个例外就是构造函数中如果出现了异常,那么这会导致已经分配的资源无法回收,下面是一个构造函数抛出异常的例子:
#include&&iostream&&#include&&string&&using&namespace&&&class&base&{&&&&&public:&&&&&&&&&base()&&&&&&&&&{&&&&&&&&&&&&&cout&&&&&I&start&to&construct&&&&&&&&&&&&&&&&&&if&(count&==&3)&&&&&&&&&&&&&&&&&&throw&string(&I&am&a&error&);&&&&&&&&&&&&&count++;&&&&&&&&&}&&&&&&&&&&~base()&&&&&&&&&{&&&&&&&&&&&&&cout&&&&&I&will&destruct&&&&&&&&&&&&&&&}&&&&&private:&&&&&&&&&static&int&&};&&int&base::count&=&0;&&int&main()&{&&&&&&&&&try{&&&&&&&&&&&&&&base&test[5];&&&&&&&&&&}&catch(...){&&&&&&&&&&&&&&cout&&&&&catch&some&error&&&&&&&&&&&&&&&}&}&上面的代码输出结果是:&I&start&to&construct&I&start&to&construct&I&start&to&construct&I&start&to&construct&I&will&destruct&I&will&destruct&I&will&destruct&catch&some&error&
在上面的代码中构造函数发生了异常,导致对应的析构函数没有执行,因此实际编程过程中应该避免在构造函数中抛出异常,如果没有办法避免,那么一定要 在构造函数中对其进行捕获进行处理.最后介绍一个知识点就是函数try语句块,如果main函数可能会抛出异常该怎么捕获?,如果构造函数中的初始化列表 可能会抛出异常该怎么捕获?下面的两个例子说明了函数try语句块的用法:
#include&&iostream&&&using&namespace&&&int&main()&try&{&&&&&throw&&main&;&}&catch(const&char*&msg)&{&&&&&cout&&&&msg&&&&&&&&&return&1;&}&main函数语句块,可以捕获main函数中抛出的异常.&class&Base&{&&&&&public:&&&&&&&&&Base(int&data,string&str)try:m_int(data),m_string(str)&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&}catch(const&char*&msg)&{&&&&&&&&&&&&&&cout&&&&&catch&a&exception&&&&&msg&&&&&&&&&&&&}&&&&&&private:&&&&&&&&&int&m_&&&&&&&&&string&m_&};&&int&main()&{&&&&&Base&base(1,&zhangyifei&);&}&
上面说了很多都是关于异常的使用,如何定义自己的异常,编写异常是否应该遵循一定的标准,在哪里使用异常,异常是否安全等等一系列的问题,下面会一一讨论的.
C++标准库给我们提供了一系列的标准异常,这些标准异常都是从exception类派生而来,主要分为两大派生类,一类是 logic_error,另一类则是runtime_error这两个类在stdexcept头文件中,前者主要是描述程序中出现的逻辑错误,例如传递了 无效的参数,后者指的是那些无法预料的事件所造成的错误,例如硬件故障或内存耗尽等,这两者都提供了一个参数类型为std::string的构造函数,这 样就可以将异常信息保存起来,然后通过what成员函数得到异常信息.
#include&&stdexcept&&#include&&iostream&&#include&&string&&using&namespace&&&class&MyError:public&runtime_error&{&public:&&&&&MyError(const&string&&msg&=&&&)&:&runtime_error(msg)&{}&&};&&&&int&main()&{&&&&&try&{&&&&&&&&&throw&MyError(&my&message&);&&&&&&&}&&&catch(MyError&&x)&{&&&&&&&&&cout&&&&x.what()&&&&&&&&&&&&}&}&
异常规格说明
假设一个项目中使用了一些第三方的库,那么第三方库中的一些函数可能会抛出异常,但是我们不清楚,那么C++提供了一个语法,将一个函数可能会抛出 的异常列出来,这样我们在编写代码的时候参考函数的异常说明即可,但是C++11中这中异常规格说明的方案已经被取消了,所以我不打算过多介绍,通过一个 例子看看其基本用法即可,重点看看C++11中提供的异常说明方案:
#include&&exception&&#include&&iostream&&#include&&cstdio&&#include&&cstdlib&&using&namespace&&&class&Up{};&class&Fit{};&void&g();&&void&f(int&i)throw(Up,Fit)&{&&&&&switch(i)&{&&&&&&&&&case&1:&throw&Up();&&&&&&&&&case&2:&throw&Fit();&&&&&&&&}&&&&&g();&}&&void&g()&{throw&47;}&&void&my_ternminate()&{&&&&&cout&&&&&I&am&a&ternminate&&&&&&&&&&exit(0);&}&&void&my_unexpected()&{&&&&&cout&&&&&unexpected&exception&thrown&&&&&&&&&&&throw&8;&&&&&&&&&&&&&&&&&&&&&&&&&}&&int&main()&{&set_terminate(my_ternminate);&set_unexpected(my_unexpected);&for(int&i&=&1;i&&=3;i++)&{&&&&&&&&&&&&&&&&&&&&&&&try&{&&&&&&&&&f(i);&&&&&&&&}catch(Up)&{&&&&&&&&&cout&&&&&Up&caught&&&&&&&&&&&&&}catch(Fit)&{&&&&&&&&&cout&&&&&Fit&caught&&&&&&&&&&&&&}catch(bad_exception)&{&&&&&&&&&cout&&&&&bad&exception&&&&&&&&&&&&&}&}&}&
上面的代码说明了异常规格说明的基本语法,以及unexpected函数的作用,以及如何自定义自己的unexpected函数,还讨论了在 unexpected函数中继续抛出异常的情况下,该如何处理抛出的异常.C++11中取消了这种异常规格说明.引入了一个noexcept函数,用于表 明这个函数是否会抛出异常
void recoup(int) noexecpt(true);& //recoup不会抛出异常
void recoup(int) noexecpt(false); //recoup可能会抛出异常
此外还提供了noexecpt用来检测一个函数是否不抛出异常.
异常安全我觉得是一个挺复杂的点,不光光需要实现函数的功能,还要保存函数不会在抛出异常的情况下,出现不一致的状态.这里举一个例子,大家在实现 堆栈的时候经常看到书中的例子都是定义了一个top函数用来获得栈顶元素,还有一个返回值是void的pop函数仅仅只是把栈顶元素弹出,那么为什么没有 一个pop函数可以&即弹出栈顶元素,并且还可以获得栈顶元素呢?
template&typename&T&&T&stack&T&::pop()&{&&&&&if(count&==&0)&&&&&&&&&throw&logic_error(&stack&underflow&);&&&&&else&&&&&&&&&return&data[--count];&}&
如果函数在最后一行抛出了一个异常,那么这导致了函数没有将退栈的元素返回,但是Count已经减1了,所以函数希望得到的栈顶元素丢失了.本质原 因是因为这个函数试图一次做两件事,1.返回值,2.改变堆栈的状态.最好将这两个独立的动作放到两个独立的函数中,遵守内聚设计的原则,每一个函数只做 一件事.我们&再来讨论另外一个异常安全的问题,就是很常见的赋值操作符的写法,如何保证赋值操作是异常安全的.
class&Bitmap&{...};&class&Widget&{&&&&&...&private:&&&&&Bitmap&*&&};&Widget&&Widget::operator=(const&Widget&&rhs)&{&&&&&delete&&&&&&pb&=&new&Bitmap(*rhs.pb);&&&&&return&*this;&}&
上面的代码不具备自我赋值安全性,倘若rhs就是对象本身,那么将会导致*rhs.pb指向一个被删除了的对象.那么就绪改进下.加入证同性测试.
Widget&&Widget::operator=(const&Widget&&rhs)&{&&&&&If(this&==&rhs)&return&*this;&&&&&&delete&&&&&&pb&=&new&Bitmap(*rhs.pb);&&&&&return&*this;&}&
但是现在上面的代码依旧不符合异常安全性,因为如果delete pb执行完成后在执行new Bitmap的时候出现了异常,则会导致最终指向一块被删除的内存.现在只要稍微改变一下,就可以让上面的代码具备异常安全性.
Widget&&Widget::operator=(const&Widget&&rhs)&{&&&&&If(this&==&rhs)&return&*this;&&&&&&Bitmap&*pOrig&=&&&&&&pb&=&new&Bitmap(*rhs.pb);&&&&&&delete&pO&&&&&return&*this;&&&}&
这个例子看起来还是比较简单的,但是用处还是很大的,对于赋值操作符来说,很多情况都是需要重载的.
【编辑推荐】
【责任编辑: TEL:(010)】
大家都在看猜你喜欢
头条头条头条原创头条
24H热文一周话题本月最赞
讲师:412709人学习过
讲师:218162人学习过
讲师:144783人学习过
精选博文论坛热帖下载排行
本书是一本知识全面、系统、专业的网络工程基础知识必备图书。全书条理清晰、逻辑性强,遵循从全局到细节,从底层基础到高层应用的顺序全面...
订阅51CTO邮刊求助~~~~一道C++编程 偶遇到错误了 不知道怎么修改~~【c++吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:289,518贴子:
求助~~~~一道C++编程 偶遇到错误了 不知道怎么修改~~收藏
源程序为#include&iostream.h&#include"link.h"void main(){ struct Card{&&&&&&},for(int i=0;i&52;i++)&&&& { LinkedList&Card& L;&&&&&&&& C&&&&&&&& cd.zf=1;&&&&&&&& cd.number=i+1;&&&&&&&& L.InsertRear(cd);&&&& }&&&& for(i=2;i&=52;i++)&&&& {&&&&&&&& L.Reset();&&&&&&&& while(!L.EndOfList())&&&&&&&& {&&&&&&&&&&&& if(L.Data().number%i==0)&&&&&&&&&&&& {&&&&&&&&&&&&&&&& L.Data().zf=(L.Data().zf+1)%2;&&&&&&&&&&&& }&&&&&&&&&&&& L.Next();&&&&&&&& }&&&& }&&&& for(L.Reset();!L.EndOfList();L.Next())&&&& {&&&&&&&& if(L.Data().zf==1)&&&&&&&&&&&& cout&&L.Data().number&&"\t";&&&& }&&&& cout&&}
c++培训课程,美国上市公司&达内&出品c++课程,15年教学经验,总监级c++讲师亲授!!达内首创&先就业后付款&模式.名企项目总监授课,成就&稀缺级&c/c++软件工程师
我知道第2行有错误,可是怎么修改呢~~~~~??一直很纳闷~~~求教一下怎么办呢!!拜谢~~~~
快试试吧,可以对自己使用挽尊卡咯~◆◆
首先大概扫了一下你程序语法上struct处应该以分号结尾 ,而且你没声明名字空间,cout,endl是无法识别的,其他具体错误,你这个是片段,最好说出报错信息
回复:3楼报错信息为:--------------------Configuration: Cpp1 - Win32 Debug--------------------Compiling...Cpp1.cppc:\documents and settings\administrator\桌面\新建文件夹\cpp1.cpp(2) : fatal error C1083: Cannot open include file: 'link.h': No such file or directoryError executing cl.exe.Cpp1.obj - 1 error(s), 0 warning(s)
没有link.h头文件,确认它存在
回复:5楼哦~~~~我知道啊!!可是怎么样去修改呢?~?~
快试试吧,可以对自己使用挽尊卡咯~◆◆
建个工程,把那个头文件放在一个工程下面。
快试试吧,可以对自己使用挽尊卡咯~◆◆
3L, 你一知半解的比这LZ强不哪去 对于老版本的C++标准,头文件的引用方式是iostream.h, 不需要 新版本的标准是去掉.h后缀, 需要加namespace, 另外C标准库头文件名前加c, 比如math.h变成cmath. 现在标准对老标准保持兼容,但是说不准什么时候就会取消了,另外老版本里面有很多问题,最好不要用 现在看这iostream.h就蛋疼, 都是给国内的垃圾教材害的.
登录百度帐号推荐应用

我要回帖

更多关于 工商年报填错不能修改 的文章

 

随机推荐