C++:理解拷贝在变量,指针,引用以及构造函数里的意义

变量,指针,引用

//拷贝与拷贝构造函数

//拷贝(copy):拷贝数据,拷贝内存

//=始终是在拷贝值,但是指针存储的是内存的地址,变量存储的是数据的值

//特别注意,在引用里面的拷贝是改变指向,没有复制的操作!


#include <string>
#include <iostream>

//拷贝与拷贝构造函数
//拷贝(copy):拷贝数据,拷贝内存
//=始终是在拷贝值,但是指针存储的是内存的地址,变量存储的是数据的值
//特别注意,在引用里面的拷贝是改变指向,没有复制的操作!
struct Vector2
{
    float x,y;
    
};
int main()
{
    //a,b是两个不同的变量,有两个内存地址,拷贝的是数据,因此a.x=2,b.x=5
    Vector2 a={2,3};
    Vector2 b=a;
    b.x=5;
    
    //如果分配在堆上,用指针,则不同  这里的拷贝是拷贝地址的数字,指向同一块内存
    Vector2* c=new Vector2();
    Vector2* d=c;
    d->x=5;
    std::cout<<a.x<<std::endl;
    std::cout<<b.x<<std::endl;
    std::cout<<(*c).x<<std::endl;
    std::cout<<(* d).x<<std::endl;

    std::cin.get();
}

//深拷贝:复制整个对象 通过 拷贝构造函数 实现(C++默认提供一个拷贝构造函数)


#include <string>
#include <iostream>
//深拷贝:复制整个对象 通过 拷贝构造函数 实现(C++默认提供一个拷贝构造函数)
class String
{
private:
    char* m_Buffer;
    unsigned int m_Size;
public:
    String(const char* string)//用指针访问字符串字面量的首地址
    {
        m_Size=(int)strlen(string);
        m_Buffer=new char[m_Size+1];//给一个空间给空终止符
        memcpy(m_Buffer, string, m_Size);//拷贝的简单化操作
        m_Buffer[m_Size]=0;//此时的长度+1后,从0开始,一共有string+1个字符串,最后一个是0,终止符
//验证
        //        std::cout<<strlen(m_Buffer)<<std::endl;
//        std::cout<<m_Buffer[m_Size-1]<<std::endl;
        
        
//        for (int i=0; i<m_Size; i++) {
//            m_Buffer[i]=string[i];
//        }
    }
    //拷贝构造函数
    //String(const String& other)=delete;//不允许复制 string2=string就会报错
    
    //深拷贝
    String(const String& other)
        :m_Size(other.m_Size)
    {
        std::cout<<"copy"<<std::endl;
        m_Buffer=new char[m_Size+1];
        memcpy(m_Buffer, other.m_Buffer, m_Size+1);//拷贝的简单化操作
    }
    
    ~String()
    {
        delete [] m_Buffer;//new,要用delete!因为我们没有用智能指针啦
    }
    
    char& operator[](unsigned int index)
    {
        return m_Buffer[index];
    }
    friend std::ostream& operator<<(std::ostream& stream,const String& string);
};
//打印字符串
std::ostream& operator<<(std::ostream& stream,const String& string)
{
    stream<<string.m_Buffer;//因为友元的设定,属于可以访问m_Buffer,然后把字符串流放进stream里
    return stream;
}

void Print(const String& string)//如果不是引用传递,这里的string会通过拷贝传值,多调用copy
{
    std::cout<<string<<std::endl;
}

int main()
{
    String string="QingXiao";
    String string2=string;//程序会崩溃。因为这里是char*的拷贝,两个指针指向了同一个内存地址,在释放的时候会两次调用析构函数,第一次后,内存已经释放了,第二次时,对应内存块不属于此程序控制,因此程序崩溃
    string2[2]='b';//没有深拷贝函数之前,可以看到两个结果都是一样的
//    std::cout<<string<<std::endl;
//    std::cout<<string2<<std::endl;
    Print(string);
    Print(string2);
    std::cin.get();//最终运行要按一下回车,才会看到崩溃结果
}

建议打断点看运行过程理解

相关推荐

  1. C++中构造函数以及默认拷贝构造函数

    2024-02-11 08:36:02       35 阅读
  2. C++关于拷贝构造函数一些理解

    2024-02-11 08:36:02       28 阅读
  3. C++指针引用区别

    2024-02-11 08:36:02       34 阅读
  4. C++ 拷贝构造函数

    2024-02-11 08:36:02       56 阅读
  5. C++ 拷贝构造函数

    2024-02-11 08:36:02       54 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-11 08:36:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-11 08:36:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-02-11 08:36:02       82 阅读
  4. Python语言-面向对象

    2024-02-11 08:36:02       91 阅读

热门阅读

  1. uniapp v-if和v-for优先级问题

    2024-02-11 08:36:02       44 阅读
  2. <网络安全>《18 数据安全交换系统》

    2024-02-11 08:36:02       44 阅读
  3. BatchNorm介绍:卷积神经网络中的BN

    2024-02-11 08:36:02       47 阅读
  4. 每日一个shell脚本之钓鱼游戏练手

    2024-02-11 08:36:02       44 阅读
  5. 命令行任务管理器的at命令

    2024-02-11 08:36:02       49 阅读
  6. 【Make编译控制 08】CMake动静态库

    2024-02-11 08:36:02       37 阅读
  7. Tiny Http源码解析

    2024-02-11 08:36:02       35 阅读
  8. 【心得】关于STM32中RTC的校准方法

    2024-02-11 08:36:02       39 阅读
  9. 学习与非学习

    2024-02-11 08:36:02       48 阅读
  10. django中实现适配器模式

    2024-02-11 08:36:02       42 阅读