问题来自C++ Primer的第十三章练习题的13.48.是这样说的:

定义一个vector<String>并在其上多次调用push_back运行你的程序,并观察String被拷贝了多少次。

其中String是在习题中自己写的一个类似标准库string的类。(第一次看,自己写的String类确实有点挫,于是直接用了github上找到的CppPrimer答案中的String类。

//String.hclass String {
public:String() : String("") {}String(const char*);String(const String&);String& operator=(const String&);String(String&&);String& operator=(String&&);~String();const char* c_str() const { return elements; }size_t size() const { return end - elements; }size_t length() const { return end - elements - 1; }private:std::pair<char*, char*> alloc_n_copy(const char*, const char*);void range_initializer(const char*, const char*);void free();private:char* elements;char* end;std::allocator<char> alloc;
};std::pair<char*, char*> String::alloc_n_copy(const char* b, const char* e)
{auto str = alloc.allocate(e - b);return{ str, std::uninitialized_copy(b, e, str) };
}
void String::range_initializer(const char* first, const char* last)
{auto newstr = alloc_n_copy(first, last);elements = newstr.first;end = newstr.second;
}
String::String(const char* s)
{char* sl = const_cast<char*>(s);while (*sl) ++sl;range_initializer(s, ++sl);
}
String::String(const String& rhs)
{range_initializer(rhs.elements, rhs.end);std::cout << "copy constructor" << std::endl;
}String& String::operator=(const String& rhs)
{auto newstr = alloc_n_copy(rhs.elements, rhs.end);free();elements = newstr.first;end = newstr.second;std::cout << "copy-assignment operator" << std::endl;return *this;
}
String::String(String &&s) :elements(s.elements), end(s.end)
{s.elements = s.end = nullptr;cout << "move constructor" << endl;
}
String& String::operator=(String &&s)
{if (this != &s){free();elements = s.elements;end = s.end;s.elements = s.end = nullptr;}cout << "move-assignment operator" << endl;return *this;
}
void String::free()
{if (elements) {std::for_each(elements, end, [this](char& c) { alloc.destroy(&c); });alloc.deallocate(elements, end - elements);}
}
String::~String()
{free();
}

String类中定义了拷贝构造和移动构造函数,并且在调用的时候打印提示信息。

一开始遇到的问题是(那时候书上还没有讲到移动构造函数,相当于把上面头文件中的移动构造给注释掉,只有拷贝构造),我随便写了测试:

void printInfo(vector<String> &v)
{cout << "size:" << v.size() << "  " << "capacity:" <<  v.capacity() << endl;
}
int main()
{String s0("hello");vector<String> vec;printInfo(vec);vec.push_back(s0);printInfo(vec);vec.push_back(s0);printInfo(vec);vec.push_back(s0);printInfo(vec);vec.push_back(s0);printInfo(vec);system("pause");return 0;
}

结果是这样的:

由于push_back是调用的copy constructor,可以看到每一次push_back除了调用一次copy constructor外还要额外调用多次。当时我没想到是因为vector中的预留空间不足,需要额外分配空间(其实就是这个原因)。

而以上是没有移动构造的时候。下面加入了移动构造后,结果变成了:

这次更加直观了,可以看到,每次push_back在copy之前还要首先将已有的元素通过调用move constructor来移动,留出空间,然后再copy添加元素。之前之所以调用的全是copy constructor是因为没有定义move constructor,而此时编译器也不会自动合成(primer后面有说),这时候只能调用拷贝构造,效率就降低了。

那么可以预料,如果在测试之前首先调用vector的reserve方法预留出空间,那么就不需要一次次调用move constructor了。

结果如下:

这次在push_back之前加了一句

vec.reserve(4);

于是不再需要分配空间。

结论:vector添加元素在空间不够的时候需要重新分配,此时对于原来已有的元素会调用对象类的move constructor,而如果对象类没有定义移动构造,则会 使用copy constructor。所以给类添加移动构造函数可以在很多时候提高效率,因为没有它只能用拷贝构造来替代,而编译器又不会自动合成一个。

Cpp Primer是本好书,就是第一次啃有点慢= =。

关于c++中vector的push_back、拷贝构造copy constructor和移动构造move constructor相关推荐

  1. vector的push_back拷贝构造和空间占用分析

    本文同步自:http://zohead.com/archives/vector-push-back-space-copy/ 这两天在实际程序中使用 STL 的 vector push_back 类对象 ...

  2. C++ vector向量pushback拷贝构造需要注意的几点

    vector 在 push_back 时的调用类对象的拷贝构造函数和析构函数有点特别,简单做下分析. 程序代码: #include <iostream> #include <vect ...

  3. C++ 中emplace_back和push_back差异

    前言 最近看rocskdb源码,发现了大量的设计模式和C++高级特性,特此补充一下,巩固基础. 问题描述 其中关于动态数组的元素添加,代码中基本将push_back抛弃掉了,全部替换为emplace_ ...

  4. [转贴]从零开始学C++之STL(二):实现一个简单容器模板类Vec(模仿VC6.0 中 vector 的实现、vector 的容量capacity 增长问题)...

    首先,vector 在VC 2008 中的实现比较复杂,虽然vector 的声明跟VC6.0 是一致的,如下: C++ Code  1 2   template < class _Ty, cla ...

  5. C++:vector的push_back()与emplace_back()

    在STL中,向vector容器添加元素的函数有2个:push_back().emplace_back() 1.push_back() 在vector容器尾部添加一个元素,用法为: arr.push_b ...

  6. opencv中vector类的介绍

    1.c++中vector的用法详解 vector(向量): C++中的一种数据结构,确切的说是一个类.它相当于一个动态的数组,当不知道数组的个数的时候 可以使用vector<int>a; ...

  7. c++中vector的用法详解

    c++中vector的用法详解 vector(向量): C++中的一种数据结构,确切的说是一个类.它相当于一个动态的数组,当程序员无法知道自己需要的数组的规模多大时,用其来解决问题可以达到最大节约空间 ...

  8. C++中vector容器为什么扩容时按照2倍或者1.5倍进行扩容

    扩容机制 首先在VS2013底下,vector的扩容操作是每次扩容*1.5:在GCC环境下是2倍. GCC下的扩容方式是以二倍形式扩容. VS2013下是以1.5倍进行扩容 所以可能会有疑问: 问题一 ...

  9. STL中Vector的内存分配机制

    一些好的公司校园招聘过程中(包括笔试.面试环节),经常会涉及到STL中vector的使用(主要是笔试)及其性能(面试)的分析.今天看了下相关文章,也写了几个小的测试程序跑了跑.算是总结下,希望对需要的 ...

最新文章

  1. MYSQL二级表的管理_MySQL分区表的管理~2
  2. Android开发笔记——常见BUG类型之内存泄露与线程安全
  3. 1滴血,2小时,验13种癌症,精度99%!日本东芝新技术引热议
  4. Maven 概要介绍
  5. 导入依赖和加上注释后,lombok gettersetter识别不到
  6. Servlet到底是个什么东西???【【博采众长】】
  7. 解读STM32标准库的程序架构 - 以GPIO操作为例
  8. 21 RadioGroup ListFragment
  9. 项目管理工具strber
  10. LOB字段存放在指定表空间 清理CLOB字段及压缩CLOB空间
  11. 分数加减乘除混合运算带答案_分数分数加减乘除混合运算练习题及答案_0.doc
  12. javascript promise
  13. OSI参考模型与排错经验谈
  14. 多步骤查询的解决方案
  15. ISIS出现(Project2.sct(7): error: L6236E: No section matches selector - no section to be FIRST/LAST.)异常
  16. 双屏幕切换成单屏,软件不显示的问题与解决方法(总结全网)
  17. 2011热门论坛排行top100
  18. 几款好看的css表格
  19. 【独立游戏】如何完成一款游戏? | 独立游戏制作
  20. 搜狗浏览器显示服务器dns,为你设置win10系统下搜狗浏览器无法解析服务器的dns地址的处理对策...

热门文章

  1. 星际公民服务器位置,《星际公民》3.0测试服务器上线 游戏实际内容展示
  2. matlab 产生每次都一样的随机数
  3. iOS开发 App内自动连接指定Wi-Fi
  4. iOS中 百度地图详解 韩俊强的博文
  5. 地大校园邮箱申请流程中国地质大学(武汉)
  6. http的了解、get/post的区别
  7. 互联网摸鱼日报(2022-10-21)
  8. Thinkpad笔记本验机2
  9. 【数据结构】B/B-树(目录树)
  10. DST 根 CA X3 证书过期问题和修复