C++ FAQ Lite[12]--赋值算符(新)

[12] 赋值算符
(Part of C++ FAQ Lite, Copyright © 1991-2001, Marshall Cline, cline@parashift.com)

简体中文版翻译:申旻nicrosoft@sunistudio.com东日制作室东日文档


FAQs in section [12]:


[12.1] 什么是“自赋值”?

自赋值就是将对象赋值给本身。例如,

 #include "Fred.hpp"     // 声明 Fred 类 
 
 void userCode(Fred& x)
 {
   x = x;   
// 自赋值
 }

很明显,以上代码进行了显式的自赋值。但既然多个指针或引用可以指向相同对象(别名),那么进行了自赋值而不知道的情况也是可能的:

 

 #include "Fred.hpp"     //  声明 Fred
 
 void userCode(Fred& x, Fred& y)
 {
   x = y;   
// 如果&x == &y就可能是自赋值
 }
 
 int main()
 {
   Fred z;
   userCode(z, z);
 }

TopBottomPrevious sectionNext section ]


[12.2] 为什么应该当心“自赋值”?

如果不注意自赋值,将会使你的用户遭受非常微妙的并且一般来说非常严重的bug。例如,如下的类在自赋值的情况下将导致灾难:

 class Wilma { };
 
 class Fred {
 public:
   Fred()                : p_(new Wilma())      { }
   Fred(const Fred& f)   : p_(new Wilma(*f.p_)) { }
  ~Fred()                { delete p_; }
   Fred& operator= (const Fred& f)
     {
       
// 差劲的代码:没有处理自赋值!
       delete p_;                
// Line #1
       p_ = new Wilma(*f.p_);    
// Line #2
       return *this;
     }
 private:
   Wilma* p_;
 };

如果有人将 Fred 对象赋给其本身,由于*thisf 是同一个对象,line #1同时删除了this->p_f.p_。而 line #2使用了已经不存在的对象*f.p_,这样很可能导致严重的灾难。

作为 Fred 类的作者,你最起码有责任确信在Fred对象上自赋值是无害的。不要假设用户不会在对象上这样做。如果对象由于自赋值而崩溃,那是你的过失。

另外:上述的Fred::operator= (const Fred&)还有第二个问题:如果在执行new Wilma(*f.p_)时,抛出了异常(例如,内存不够的异常或者Wilma的拷贝构造函数中的异常 ), this->p_将成为悬空指针——它所指向的内存不再是可用的。这可以通过在删除就对象前创建对象来解决。

TopBottomPrevious sectionNext section ]


[12.3] 好,好;我会处理自赋值的。但如何做呢? UPDATED!

[Recently reworded the last paragraph (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes .]

在你创建类的每时每刻,都应该当心自赋值。这并不意味着需要为你所有的类都增加额外的代码:只要对象优美地处理自赋值,而不管是否必须增加额外的代码。

如果不需要为赋值算符增加额外代码,这里有一个简单而有效的技巧:

 Fred& Fred::operator= (const Fred& f)
 {
   if (this == &f) return *this;   
// 优美地处理自赋值
 
   
// 此处写正常赋值的代码...
 
   return *this;
 }

显式的测试并不总是必要的。例如,如果修正前一个 FAQ 中的赋值算符使之处理new 抛出的异常和/或Wilma类的拷贝构造函数抛出的异常,可能会写出如下的代码。注意这段代码有(令人高兴的)自动处理自赋值的附带效果:

 

 Fred& Fred::operator= (const Fred& f)
 {
   
// 这段代码优美地(但隐含的)处理自赋值
   Wilma* tmp = new Wilma(*f.p_);   
// 如果异常在此处被抛出也没有问题
   delete p_;
   p_ = tmp;
   return *this;
 }

在象这个例子的情况下(自赋值是无害的但是低效),一些程序员想通过增加另外的不必要的测试,如“if (this == &f) return *this;”来改善自赋值时的效率。通常来说,使自赋值情况更高效而使得非自赋值情况更低效的折衷是错误的。例如,为Fred类的赋值算符增加如上的if测试会使得非自赋值情况更低效(一个额外的(而且不必要的)条件分支)。如果自赋值实际上一千次才发生一次,那么 if 将浪费99.9%的时间周期。

TopBottomPrevious sectionNext section ]


E-Mail E-mail the author
C++ FAQ LiteTable of contentsSubject indexAbout the author©Download your own copy ]
Revised Apr 8, 2001

阅读终点,创作起航,您可以撰写心得或摘录文章要点写篇博文。去创作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 这是一个 Python 代码实现示例: ``` array = [0] * 101 for i in range(1, 11): array[i] = i print(array) ``` 这样,您就可以将1到10的值循环赋值给一个具有101个元素的数组了。 ### 回答2: 将1-10循环赋值给一个又101个元素的数组是可以实现的。实现的方法如下: 首先,我们可以使用循环结构来遍历101个元素的数组。设定一个循环的计数器变量,从0开始循环到100,每次循环加1。 在循环的每一次迭代中,我们可以使用取余运算符(%)将1-10循环赋值给数组元素。取余运算符可以将一个数与另一个数相除,然后返回余数。 具体实现时,我们可以将计数器变量对10取余,得到的余数加1即可作为数组元素的值。这样就能够实现1-10的循环赋值。同时,我们需要注意数组索引从0开始,所以在赋值时需要将计数器变量加1作为索引。 以下是伪代码表示上述实现过程: ``` //创建一个长度为101的数组 int[] arr = new int[101]; for (int i = 0; i < 101; i++) { //将1-10循环赋值给数组元素 arr[i] = (i % 10) + 1; } ``` 通过以上步骤,我们可以将1-10循环赋值给一个101个元素的数组。数组的前10个元素将会是1 到 10 的循环,后面的元素也将以相同的模式进行循环赋值。 ### 回答3: 将1-10循环赋值给一个有101个元素的数组,那么数组的前10个元素就是1-10的循环。我们可以使用循环结构来实现这个过程。具体的步骤如下: 1. 创建一个有101个元素的数组,我们可以使用数组的索引来表示元素的位置,从0到100。 2. 使用一个循环结构,循环的次数为数组的长度101。 3. 在循环中,使用取余操作符(%)将循环变量与10取余,将余数加1赋值给当前索引位置的数组元素。 4. 这样,当循环变量为0时,整数除以10的余数为0,加1得到1,赋值给数组的第0个元素;循环变量为1时,整数除以10的余数为1,加1得到2,赋值给数组的第1个元素;以此类推。 5. 当循环变量为10时,整数除以10的余数为0,加1得到1,赋值给数组的第10个元素。此时,整个1-10的循环赋值过程完成。 6. 最后,数组的前10个元素分别为1、2、3、4、5、6、7、8、9、10,之后的元素可以根据循环特性进行逻辑推断,为11、12、13、...、100、1、2、3、...、8、9、10。 通过以上步骤,我们可以将1-10循环赋值给一个有101个元素的数组。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nicrosoft

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值