在String中添加移动构造函数和移动赋值运算符
13.50 没有定义析构函数
#include<iostream>
#include<string>
#include<memory>
#include<utility>
#include<cstring>
#include<vector>
using namespace std; class String
{
public:
String():elements(nullptr),first_free(nullptr) {}
String(char *c);
String(const String&);
String& operator=(const String&);
string* begin() const { return elements;}
string* end() const { return first_free;} String(String &&);
String& operator=(String &&);
private:
static allocator<string> alloc;
string *elements;
string *first_free;
}; allocator<string> String::alloc;
String::String(char *c)
{
size_t capacity=strlen(c);
auto data=alloc.allocate(capacity);
auto dest=data;
string s;
s.copy(c,strlen(c));
alloc.construct(dest++,s);
elements=data;
first_free=dest;
} String::String(const String &s)
{
cout<<"copy construct"<<endl;
auto capacity=s.end()-s.begin();
auto data=alloc.allocate(capacity);
uninitialized_copy(s.begin(),s.end(),data);
elements=data;
first_free=data+capacity;
} String& String::operator=(const String &s)
{
cout<<"copy = construct"<<endl;
auto capacity=s.end()-s.begin();
auto data=alloc.allocate(capacity);
uninitialized_copy(s.begin(),s.end(),data);
if(elements)
{
auto begin=elements;
auto end=first_free;
while(begin!=end)
alloc.destroy(begin++);
alloc.deallocate(elements,first_free-elements);
}
elements=data;
first_free=data+capacity;
return *this;
} String::String(String &&s):elements(s.elements),first_free(s.first_free)
{
cout<<"move construct"<<endl;
s.elements=s.first_free=nullptr;
} String& String::operator=(String &&s)
{
cout<<"move = construct"<<endl;
if(this!=&s)
{
if(elements)
{
auto begin=elements;
auto end=first_free;
while(begin!=end)
alloc.destroy(begin++);
alloc.deallocate(elements,first_free-elements);
}
}
elements=s.elements;
first_free=s.first_free;
s.elements=s.first_free=nullptr;
return *this;
} int main()
{
vector<String> vec;
char ch[]="hello";
char ch1[]="world!";
cout<<vec.capacity()<<endl;
cout<<endl;
vec.push_back(String(ch));
cout<<vec.capacity()<<endl;
cout<<endl;
vec.push_back(String(ch1));
cout<<vec.capacity()<<endl;
cout<<endl;
vec.push_back(String(ch));
cout<<vec.capacity()<<endl;
cout<<endl;
vec.push_back(String(ch1));
cout<<vec.capacity()<<endl;
cout<<endl;
vec.push_back(String(ch1));
cout<<vec.capacity()<<endl;
cout<<endl;
vec.push_back(String(ch1));
cout<<vec.capacity()<<endl;
return ;
}
运行结果如下: 结果中出现移动构造函数是因为调用String构造函数返回的结果是右值
定义析构函数时:
#include<iostream>
#include<string>
#include<memory>
#include<utility>
#include<cstring>
#include<vector>
using namespace std; class String
{
public:
String():elements(nullptr),first_free(nullptr){}
String(char *c);
String(const String&);
String& operator=(const String&);
string* begin() const { return elements;}
string* end() const { return first_free;}
//一定要定义析构函数,否则就算定义了移动构造函数还是不会调用,只会调用拷贝构造函数
~String()
{
if(elements)
{
auto begin=elements;
auto end=first_free;
while(begin!=end)
alloc.destroy(begin++);
alloc.deallocate(elements,first_free-elements);
}
}
String(String &&) noexcept;
String& operator=(String &&) noexcept;
private:
static allocator<string> alloc;
string *elements;
string *first_free;
}; allocator<string> String::alloc;
String::String(char *c)
{
size_t capacity=strlen(c);
auto data=alloc.allocate(capacity);
auto dest=data;
string s;
s.copy(c,strlen(c));
alloc.construct(dest++,s);
elements=data;
first_free=dest;
} String::String(const String &s)
{
cout<<"copy construct"<<endl;
auto capacity=s.end()-s.begin();
auto data=alloc.allocate(capacity);
uninitialized_copy(s.begin(),s.end(),data);
elements=data;
first_free=data+capacity;
} String& String::operator=(const String &s)
{
cout<<"copy = construct"<<endl;
auto capacity=s.end()-s.begin();
auto data=alloc.allocate(capacity);
uninitialized_copy(s.begin(),s.end(),data);
if(elements)
{
auto begin=elements;
auto end=first_free;
while(begin!=end)
alloc.destroy(begin++);
alloc.deallocate(elements,first_free-elements);
}
elements=data;
first_free=data+capacity;
return *this;
} String::String(String &&s) noexcept :elements(s.elements),first_free(s.first_free)
{
cout<<"move construct"<<endl;
s.elements=s.first_free=nullptr;
} String& String::operator=(String &&s) noexcept
{
cout<<"move = construct"<<endl;
if(this!=&s)
{
if(elements)
{
auto begin=elements;
auto end=first_free;
while(begin!=end)
alloc.destroy(begin++);
alloc.deallocate(elements,first_free-elements);
}
}
elements=s.elements;
first_free=s.first_free;
s.elements=s.first_free=nullptr;
return *this;
} int main()
{
vector<String> vec;
char ch[]="hello";
char ch1[]="world!";
cout<<vec.capacity()<<endl;
cout<<endl;
String ss(ch);
vec.push_back(ss);
cout<<vec.capacity()<<endl;
cout<<endl;
vec.push_back(String(ch1));
cout<<vec.capacity()<<endl;
cout<<endl;
vec.push_back(String(ch));
cout<<vec.capacity()<<endl;
cout<<endl;
vec.push_back(String(ch1));
cout<<vec.capacity()<<endl;
cout<<endl;
vec.push_back(String(ch1));
cout<<vec.capacity()<<endl;
cout<<endl;
vec.push_back(String(ch1));
cout<<vec.capacity()<<endl;
cout<<"\n"; std::vector<String> v;
String s;
for (unsigned i = ; i != ; ++i)
{
std::cout << v.capacity() << "\n";
v.push_back(s);
}
return ;
}
运行结果如下:
在String中添加移动构造函数和移动赋值运算符的更多相关文章
- [JS]给String对象添加方法,使传入的字符串字符之间以空格分开输出
看到一个这样子的面试题: 给String对象添加一个方法,传入一个string类型的参数,然后将string的每一个字符间加空格返回,例如:addSpace("hello world&quo ...
- 从源代码的角度聊聊java中StringBuffer、StringBuilder、String中的字符串拼接
长久以来,我们被教导字符串的连接最好用StringBuffer.StringBuilder,但是我们却不知道这两者之间的区别.跟字符串相关的一些方法中总是有CharSequence.StringBuf ...
- C++中 类的构造函数理解(一)
C++中 类的构造函数理解(一) 写在前面 这段时间完成三个方面的事情: 1.继续巩固基础知识(主要是C++ 方面的知识) 2.尝试实现一个iOS的app,通过完成app,学习iOS开发中要用到的知识 ...
- 在RichTextBox控件中添加图片和文字
public void SetText(RichTextBox rtb) { rtb.Text = "在RichTextBox控件中添加图片和文字" + Environment.N ...
- 008.Adding a model to an ASP.NET Core MVC app --【在 asp.net core mvc 中添加一个model (模型)】
Adding a model to an ASP.NET Core MVC app在 asp.net core mvc 中添加一个model (模型)2017-3-30 8 分钟阅读时长 本文内容1. ...
- 编写高质量代码改善C#程序的157个建议——建议106:为静态类添加静态构造函数
建议106:为静态类添加静态构造函数 静态类可以拥有构造方法,这就是静态构造方法.静态构造方法与实例构造方法比较有几个自己的特点: 只被执行一次,且在第一次调用类成员之前被运行时执行. 代码无法调用它 ...
- Vue.set 向响应式对象中添加响应式属性,及设置数组元素触发视图更新
一.为什么需要使用Vue.set? vue中不能检测到数组和对象的两种变化: 1.数组长度的变化 vm.arr.length = 4 2.数组通过索引值修改内容 vm.arr[1] = ‘aa’ Vu ...
- spring中bean的构造函数,Autowired(Value)注入与@PostConstruct调用顺序
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/yyysylvia/article/deta ...
- 用Retrofit发送请求中添加身份验证
用Retrofit发送请求中添加身份验证====================在安卓应用开发中, retrofit可以极大的方便发送http网络请求,不管是GET, POST, 还是PUT, DEL ...
随机推荐
- 定时显示div
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " http://www.w3.org ...
- JavaScript自学代码--(四)
//JavaScript Window - 浏览器对象模型 window.document.getElementById("header"); //等价于 document.get ...
- 反射实体自动生成EasyUi DataGrid模板
用EasyUi Datagrid展示数据的时候总是要一下这样一段代码 <table id="dt" class="easyui-datagrid"> ...
- settimeout vs setinternal
http://blog.sina.com.cn/s/blog_6b1ab3be0100pzmo.html http://www.360doc.com/content/11/0412/17/100779 ...
- OpenIOC
http://wenku.it168.com/d_926300.shtml OpenIOC http://safe.it168.com/a2015/1208/1790/000001790446.sht ...
- ANDROID_MARS学习笔记_S03_003_LocationManager、LocationListener
一.简介 二.代码1.xml (1)AndroidManifest.xml 增加 <uses-permission android:name="android.permission.A ...
- vs2005 ,2008,2010中引入app.manifest(即c#程序在win7下以管理员权限运行方法)
打开VS2005.VS2008.VS2010工程,查看工程文件夹中的Properties文件夹下是否有app.manifest这个文件:如没有,按如下方式创建:鼠标右击工程在菜单中选择“属性”,点击工 ...
- 【CF】86 B. Petr#
误以为是求满足条件的substring总数(解法是KMP分别以Sbeg和Send作为模式串求解满足条件的position,然后O(n^2)或者O(nlgn)求解).后来发现是求set(all vali ...
- 【Python Network】使用DOM生成XML
单纯的为DOM树添加结点. #!/usr/bin/env python # Generating XML with DOM - Chapter 8 - domgensample.py from xml ...
- Linux修改文件时候出现崩溃,产生了一个.swap交换文件,如何修复?
有时候在用vim打开文件时提示类似以下的信息: E325: 注意 发现交换文件 ".exportcert.cpp.swp" 所有者: liuchuanliang 日期: Th ...