VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

有编程疑问吗?还请到提问专区发帖提问!
搜索
查看: 183|回复: 2

[求助] 关于移动构造的几个小问题

[复制链接]
35_avatar_middle
在线会员 Jeff_ 发表于 2018-11-19 11:08:27 | 显示全部楼层 |阅读模式
6驿站币
本帖最后由 Jeff_ 于 2018-11-19 21:05 编辑
  1. #include <iostream>
  2. using namespace std;

  3. // interface
  4. class Useless
  5. {
  6. private:
  7.     int n;          // number of elements
  8.     char * pc;      // pointer to data
  9.     static int ct;  // number of objects
  10.     void ShowObject() const;
  11. public:
  12.     Useless();
  13.     explicit Useless(int k);
  14.     Useless(int k, char ch);
  15.     Useless(const Useless & f); // regular copy constructor
  16.     Useless(Useless && f);      // move constructor
  17.     ~Useless();
  18.     Useless operator+(const Useless & f)const;
  19. // need operator=() in copy and move versions
  20.     void ShowData() const;
  21. };

  22. // implementation
  23. int Useless::ct = 0;

  24. Useless::Useless()
  25. {
  26.     ++ct;
  27.     n = 0;
  28.     pc = nullptr;
  29.     cout << "default constructor called; number of objects: " << ct << endl;
  30.     ShowObject();
  31. }

  32. Useless::Useless(int k) : n(k)
  33. {
  34.     ++ct;
  35.     cout << "int constructor called; number of objects: " << ct << endl;
  36.     pc = new char[n];
  37.     ShowObject();
  38. }

  39. Useless::Useless(int k, char ch) : n(k)
  40. {
  41.     ++ct;
  42.     cout << "int, char constructor called; number of objects: " << ct << endl;
  43.     pc = new char[n];
  44.     for (int i = 0; i < n; i++)
  45.         pc[i] = ch;
  46.     ShowObject();
  47. }

  48. Useless::Useless(const Useless & f): n(f.n)
  49. {
  50.     ++ct;
  51.     cout << "copy const called; number of objects: " << ct << endl;
  52.     pc = new char[n];
  53.     for (int i = 0; i < n; i++)
  54.         pc[i] = f.pc[i];
  55.     ShowObject();
  56. }

  57. Useless::Useless(Useless && f): n(f.n)
  58. {
  59.     ++ct;
  60.     cout << "move constructor called; number of objects: " << ct << endl;
  61.     pc = f.pc;       // steal address
  62.     f.pc = nullptr;  // give old object nothing in return
  63.     f.n = 0;
  64.     ShowObject();
  65. }

  66. Useless::~Useless()
  67. {
  68.     cout << "destructor called; objects left: " << --ct << endl;
  69.     cout << "deleted object:\n";
  70.     ShowObject();
  71.     delete [] pc;
  72. }

  73. Useless Useless::operator+(const Useless & f)const
  74. {
  75.     cout << "Entering operator+()\n";
  76.     Useless temp = Useless(n + f.n);
  77.     for (int i = 0; i < n; i++)
  78.         temp.pc[i] = pc[i];
  79.    for (int i = n; i < temp.n; i++)
  80.         temp.pc[i] = f.pc[i - n];
  81.     cout << "temp object:\n";
  82.     cout << "Leaving operator+()\n";
  83.     return temp;
  84. }

  85. void Useless::ShowObject() const
  86. {
  87.     cout << "Number of elements: " << n;
  88.     cout << " Data address: " << (void *) pc << endl;
  89. }

  90. void Useless::ShowData() const
  91. {
  92.     if (n == 0)
  93.         cout << "(object empty)";
  94.     else
  95.         for (int i = 0; i < n; i++)
  96.             cout << pc[i];
  97.     cout << endl;
  98. }

  99. // application
  100. int main()
  101. {
  102.     {
  103.         Useless one(10, 'x');
  104.         Useless two = one;          // calls copy constructor
  105.         Useless three(20, 'o');
  106.         //Useless four(one + three);  // calls operator+(), move constructor
  107.                 Useless four = one + three;
  108.         cout << "object one: ";
  109.         one.ShowData();
  110.         cout << "object two: ";
  111.         two.ShowData();
  112.         cout << "object three: ";
  113.         three.ShowData();
  114.         cout << "object four: ";
  115.         four.ShowData();
  116.     }
  117.     // cin.get();
  118. }
复制代码


这里Useless four(one + three);  调用移动构造,我自己运行了下,是先进行+法的重载,可是加法的重载还是创建了临时对象temp,然后返回temp时调用移动构造。

问题: 1.移动构造的好处不就是可以省去中间临时对象的复制与析构吗,那这里同样创建了中间临时对象的意义是什么?
           2.既然这里中间已经创建了临时对象,这个临时对象不是应该调用的复制构造吗?为什么这个temp对象还是会继续调用移动构造?

最佳答案

查看完整内容

1、移动构造的好处确实是省去中间临时对象的再次创建,但是 Useless four(one + three); 创建的临时对象跟移动构造没有关系,而是调用 Useless operator+(const Useless & f) const; 函数创建的,因为其返回值就是个新的对象,所以肯定会创建个临时对象; 2、因为第一步创建的是一个临时对象,所以才会调用移动构造,如果不是一个临时对象可能就直接调用拷贝构造了,明白了吗? 具体可以看看这篇文章,感觉讲解的挺好! C ...




上一篇:读取字符串中字符异常
下一篇:c++应用层实现文件的跟踪与修改

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

51_avatar_middle
online_admins Syc 发表于 2018-11-19 11:08:28 | 显示全部楼层
1、移动构造的好处确实是省去中间临时对象的再次创建,但是 Useless four(one + three); 创建的临时对象跟移动构造没有关系,而是调用 Useless operator+(const Useless & f) const; 函数创建的,因为其返回值就是个新的对象,所以肯定会创建个临时对象;

2、因为第一步创建的是一个临时对象,所以才会调用移动构造,如果不是一个临时对象可能就直接调用拷贝构造了,明白了吗?

具体可以看看这篇文章,感觉讲解的挺好!

C++拷贝构造、移动构造与返回值优化
https://blog.csdn.net/andylau00j/article/details/79725305

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复

使用道具 举报

74_avatar_middle
在线会员 zuiwuchang 发表于 2018-11-20 10:21:23 | 显示全部楼层
本帖最后由 zuiwuchang 于 2018-11-20 10:23 编辑

移動構造 不會省去 臨時對象的 創建 而是 減小 臨時對象的 構造 成本 以 std::string 爲例子

  1. //string 的 move 簽名
  2. string(std::string&& r)
复制代码


r 是一個右值 代表 沒有人會在使用了 所以 新建的 std::string 直接 將 char * 指針 指向 r 保存的 char* 即可 且告訴 r 析構時 不用 釋放 char* 了 因爲 指針被 新string 接管了
(stl 容器 通常都提供了 swap 函數 可以 將 內部保存的 指針/引用管理權 交換出來 你可以用一個 空的 容器 與其交互 來達到 移交控制權的 功能)
而且 爲什麼 是 && 而不是 const && 就是 因爲 r 是 可寫的 你需要 在move 構造中 將它的 資源 移交出來 而不是 copy 一份 資源

在 copy 構造時 則是 申請了 一塊 和 r 保存的 char* 同樣 大小的新 指針 並使用 strcopy 之類的 函數 將 r 的字符串 內容 copy到 新指針中

所以 對於自己實現的 class 要使用 move 帶來的好處 需要 其 管理的 資源 能夠被 移交 並實現 move 語義來 移交資源

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号tongdun|网站地图wx_jqr

GMT+8, 2018-12-14 00:55

Powered by Discuz! X3.4

© 2009-2018 cctry.com

快速回复 返回顶部 返回列表