在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 0;
}

运行结果如下:  结果中出现移动构造函数是因为调用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 = 0; i != 4; ++i)
    {
        std::cout << v.capacity() << "\n";
        v.push_back(s);
    }
    return 0;
}

运行结果如下:

时间: 2024-11-19 00:51:13

在String中添加移动构造函数和移动赋值运算符的相关文章

继承中的的构造函数问题

代码如下: 1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Teacher t1 = new Teacher("许大虾", 23, "[email protected]", 10000); 6 Student s1 = new Student("许大虾", 23, "[email protected]", "100001"); 7 }

手动添加Servlet构造函数出现的问题及猜想

我们需要用到servlet的时候,都是右键,新建一个servlet,但是有人注意到一个细节没有,当我们手动给我们的servlet添加一个构造函数时候,会出现什么状况呢? 1.尝试添加无参构造函数 直接上代码 public class Test extends HttpServlet { Test(String a){ System.out.println("这是构造函数"); } @Override protected void doGet(HttpServletRequest req

Vue.set 向响应式对象中添加响应式属性,及设置数组元素触发视图更新

一.为什么需要使用Vue.set? vue中不能检测到数组和对象的两种变化: 1.数组长度的变化 vm.arr.length = 4 2.数组通过索引值修改内容 vm.arr[1] = ‘aa’ Vue.$set(target,key,value):可以动态的给数组.对象添加和修改数据,并更新视图中数据的显示. vue在构造函数new Vue()时,就通过Object.defineProperty中的getter和setter 这两个方法,完成了对数据的绑定.所以直接通过vm.arr[1] =

asp.net core 3.0在Microsoft.Extensions.Logging中添加log4net支持

1. 引入log4net.Microsoft.Extensions.Logging.Log4Net.AspNetCore包 2. 添加log4net配置文件 3. 在Program中添加如下代码: public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureLogging((context, logger) => { logger.ClearPr

jsp实现仿QQ空间新建多个相册名称,向相册中添加照片

工具:Eclipse,Oracle,smartupload.jar:语言:jsp,Java:数据存储:Oracle. 实现功能介绍: 主要是新建相册,可以建多个相册,在相册中添加多张照片,删除照片,删除相册,当相册下有照片时先删除照片才能删除相册. 因为每个相册和照片要有所属人,所以顺带有登录功能. 声明:只是后端实现代码,前台无任何样式,代码测试可行,仅供参考. 代码: 数据库连接帮助类: public class JDBCHelper { public static final String

[Asp.net MVC]Asp.net MVC5系列——在模型中添加验证规则

目录 概述 在模型中添加验证规则 自定义验证规则 伙伴类的使用 总结 系列文章 [Asp.net MVC]Asp.net MVC5系列——第一个项目 [Asp.net MVC]Asp.net MVC5系列——添加视图 [Asp.net MVC]Asp.net MVC5系列——添加模型 [Asp.net MVC]Asp.net MVC5系列——从控制器访问模型中的数据 [Asp.net MVC]Asp.net MVC5系列——添加数据 概述 上篇文章中介绍了添加数据,在提交表单的数据的时候,我们需

VS中添加预处理宏的方法

VS中添加预处理宏的方法 除了在.c及.h中添加宏定义之外,还可以采用如下方法添加宏定义: 1.若只需要定义一个宏(如#define DEBUG),可以右键点击工程-->属性-->c/c++-->预处理器-->预处理器定义,点击下拉框中的编辑,输入想要定义的宏: 2.如果还需要定义宏的内容(如#define inline __inline),可以右键点击工程-->属性-->c/c++-->命令行,在其它选项中输入如下内容: /D"inline"

Asp.net MVC]Asp.net MVC5系列——在模型中添加

目录 概述 在模型中添加验证规则 自定义验证规则 伙伴类的使用 总结 系列文章 [Asp.net MVC]Asp.net MVC5系列--第一个项目 [Asp.net MVC]Asp.net MVC5系列--添加视图 [Asp.net MVC]Asp.net MVC5系列--添加模型 [Asp.net MVC]Asp.net MVC5系列--从控制器访问模型中的数据 [Asp.net MVC]Asp.net MVC5系列--添加数据 概述 上篇文章中介绍了添加数据,在提交表单的数据的时候,我们需

Eclipse中java向数据库中添加数据

前面详细写过如何连接数据库的具体操作,下面介绍向数据库中添加数据. 注意事项:如果参考下面代码,需要 改包名,数据库名,数据库账号,密码,和数据表(数据表里面的信息) 1 package com.ningmeng; 2 3 import java.sql.*; 4 5 /** 6 * 1:向数据库中添加数据 7 * @author biexiansheng 8 * 9 */ 10 public class Test01 { 11 12 public static void main(String