Part6 数组、指针与字符串 6.12 对象复制与移动

1 深层复制与浅层复制
浅层复制:实现对象间数据元素的一一对应复制。
深层复制:当被复制的对象数据成员是指针类型时,不是复制该指针成员本身,而是将指针所指对象进行复制。

//6-22 对象的深层复制
#include <iostream>
#include <cassert>
using namespace std;//Point同6-18
class Point{
public:
    Point():x(0),y(0){
        cout << "Default Constructor called." << endl;
    }
    Point(int x, int y):x(x),y(y){
        cout << "Constructor called." << endl;
    }
    ~Point(){cout << "Destructor called." << endl;}
    int getX() const {return x;}
    int getY() const {return y;}
    void move(int newX, int newY){
        x = newX;
        y = newY;
    }
private:
    int x,y;
};
class ArrayOfPoints{//动态数组类
public:
    ArrayOfPoints(int size):size(size){
        points = new Point[size];
    }
    ArrayOfPoints(const ArrayOfPoints& pointsArray);//新加的复制构造函数
    ~ArrayOfPoints(){
        cout << "Deleting..." << endl;
        delete[] points;
    }
    Point& element(int index){//element函数来取数组的元素
        assert(index >= 0 && index < size);//下标不能越界
        return points[index];//返回引用可以用来操作封装数组对象内部的数组元素,返回值则不能
    }
private:
    Point *points;//指向动态数组首地址
    int size;
};
ArrayOfPoints::ArrayOfPoints(const ArrayOfPoints& v){//新加的复制构造函数,实现深层复制
    size = v.size;
    points = new Point[size];
    for(int i = 0; i < size; i++)
        points[i] = v.points[i];
}
int main() {
    int count;
    cout << "Please enter the count of points: ";
    cin >> count;
    ArrayOfPoints pointsArray1(count); //创建对象数组
    pointsArray1.element(0).move(5,10);
    pointsArray1.element(1).move(15,20);
    ArrayOfPoints pointsArray2(pointsArray1); //创建副本

    cout << "Copy of pointsArray1:" << endl;
    cout << "Point_0 of array2: " << pointsArray2.element(0).getX() << ", "
         << pointsArray2.element(0).getY() << endl;
    cout << "Point_1 of array2: " << pointsArray2.element(1).getX() << ", "
         << pointsArray2.element(1).getY() << endl;

    pointsArray1.element(0).move(25, 30);
    pointsArray1.element(1).move(35, 40);
    cout <<"After the moving of pointsArray1:"<<endl;
    cout << "Point_0 of array2: " << pointsArray2.element(0).getX() << ", "
         << pointsArray2.element(0).getY() << endl;
    cout << "Point_1 of array2: " << pointsArray2.element(1).getX() << ", "
         << pointsArray2.element(1).getY() << endl;
    return 0;
}


2 移动构造
C++11 标准中提供了一种新的构造方法——移动构造。
C++11 引入移动语义:
源对象资源的控制权全部交给目标对象

当临时对象在被复制后,就不再被利用了。我们完全可以把临时对象的资源直接移动,这样就避免了多余的复制操作。

//1 使用深层复制构造函数
#include<iostream>
using namespace std;
class IntNum{
public:
    IntNum(int x = 0):xptr(new int(x)){//构造函数
        cout << "Calling constructor..." << endl;
    }
    IntNum(const IntNum &n):xptr(new int(*n.xptr)){//复制构造函数(.优先级高于*)
        cout << "Calling copy constructor..." << endl;
    }
    ~IntNum(){//析构函数
        delete xptr;
        cout << "Destructing..." << endl;
    }
    int getInt(){return *xptr;}
private:
    int *xptr;
};
IntNum getNum(){//返回值为IntNum类对象
    IntNum a;
    return a;//返回时调用复制构造,构造一个临时无名对象给主函数,a自己被析构
}
int main(){
    cout << getNum().getInt() << endl;//这里析构临时无名对象
    return 0;
}
//2 使用移动构造函数
#include<iostream>
using namespace std;
class IntNum{
public:
    IntNum(int x = 0):xptr(new int(x)){
        cout << "Calling constructor..." << endl;
    }
    IntNum(const IntNum &n):xptr(new int(*n.xptr)){
        cout << "Calling copy constructor..." << endl;
    }
    IntNum(IntNum &&n):xptr(n.xptr){//移动构造函数,用参数对象成员的指针初始化当前成员的指针
        n.xptr = nullptr;//这样析构函数delete空指针,不会发生多次析构
        cout << "Calling move constructor..." << endl;
    }
    ~IntNum(){
        delete xptr;
        cout << "Destructing..." << endl;
    }
    int getInt(){return *xptr;}
private:
    int *xptr;
};
IntNum getNum(){
    IntNum a;
    return a;
}
int main(){
    cout << getNum().getInt() << endl;
    return 0;
}
时间: 2025-01-17 22:45:17

Part6 数组、指针与字符串 6.12 对象复制与移动的相关文章

指针 指针与数组 指针与字符串 指针与函数 结构体与指针 宏

指针 指针与数组 指针与字符串 指针与函数?? 指针与数组 1.数组名:数组元素首地址 eg: int array[3]={1,3,6}; 这里array 恒等于&array[0] 2.int *p = a; int *p = 0; int a[]={0}; 3.int *p = a; 均指向数组的首地址 *p是? *(p+1)是?(*p)+1是? *(p+1)决定向下移动几个字节是类型 4.指针可以当数组名使用 p[1] = 3; 恒等于a[1] ;恒等于*(p+1);恒等于*(a+1) 5.

JS对象复制

在JavaScript很多人复制一个对象的时候都是直接用"=",因为大家都觉得脚本语言是没有指针.引用.地址之类的,所以直接用"="就可以把一个对象复制给另外一个对象,如下代码: var i1 = 1; var i2 = i1; i2 = 2; alert("i1:"+i1+",i2:"+i2); 输出结果:i1:1 , i2:2 但可能没有发现,这种“复制”用在对象(object)类型是“错误”的,因为这只是把对象的地址复制

Part6 数组、指针与字符串 6.10 智能指针 6.11 vector对象

6.10 智能指针C++11 提供智能指针的数据类型,对垃圾回收技术提供了一些支持,实现一定程度的内存管理 unique_ptr:不允许多个指针共享资源,可以用标准库中的move函数转移指针shared_ptr:多个指针共享资源weak_ptr:可复制shared_ptr,但其构造或者释放对资源不产生影响 6.11 vector对象为什么需要vector? 封装任何类型的动态数组,自动创建和删除. 数组下标越界检查. 例6-18 中封装的ArrayOfPoints也提供了类似功能,但只适用于一种

关于指针与数组定义的字符串

将指针指向一串字符串(char *a = "abcdef";),可以以 “printf("a[2] = %c\n", a[2])“ 这种方式输出字符串中第三个字符.但不能这样 “a[2] = 'G' “ 妄图将字符串中的第三个字符‘c'改为‘G‘.至于为什么,我现在是不知道了.先看代码. 1 #include <stdio.h> 2 3 int main(void) 4 { 5 char *a = "abcdef"; 6 printf

C++——指针---指向数组的指针---指向字符串的指针--指向函数的指针--指针的指针--指针的引用

一.指向数组的指针 代码示例1: 1 int main() 2 { 3 int a[10]={0,2,4,6,8,10,12,14,16,18}; 4 int *p; 5 for(p=&a[0];p<&a[0]+10;p++) 6 printf("%d ",*p); 7 } 代码示例2: int a[10]={0,2,4,6,8,10,12,14,16,18}; int *p; p=a; printf("%d\n",*(a+5));//注意加括

指针进阶 - 字符串与指针 &amp; 数组与指针

昨天的随笔里忘记提的重要一点: 指针指向的地址是有长度的,但是指针就是个针,一个针只有一个针尖,只能指向一个地址. 当我们用这种方式测量指针长度时 char *pstring; printf("%d\n", sizeof(*pstring)); 实际上我们测的不是指针占据的内存大小,而是指针指向的数据占据的内存大小,哪怕为空.由于代码中是char型,所以输出结果为1. 当我们测量却忘记带 * 号时,如: printf("%d\n", sizeof(pstring))

golang 数据一 &nbsp; (字符串、数组和数组指针)

从如下几个方面介绍GO语言的数据 1. 字符串 2. 数组 3. 切片 4. 字典 5. 结构 字符串 Go语言中的字符串是由一组不可变的字节(byte)序列组成从源码文件中看出其本身是一个复合结构 string.go  type stringStruct struct {     str unsafe.Pointer         len int } 字符串中的每个字节都是以UTF-8编码存储的Unicode字符字符串的头部指针指向字节数组的开始但是没有NULL或'\0'结尾标志. 表示方式

求字符串长度 strlen(数组指针两种方式)

问题: 求字符串中所含有字符的个数(包括空格),即求字符串长度: #include <stdio.h> #include <assert.h> int _strlen(const char* str) { assert(str != NULL); int i=0; for(;*str++!='\0';i++); //for(;str++!=NULL;i++);//有些说这句也可以,但执行结果是死循环,str++即使越界也未必为NULL; return i; } int _strle

关于DELPHI数组,指针,字符串转换的例子!(转)

var   aa:   array [0..5] of Char;   bb:Pointer;   cc:string;   dd:PChar; procedure TForm1.Button1Click(Sender: TObject);begin dd:='abcdef'; //以下是pchar内容转数组FillChar(aa,length(dd),#0);Move(dd^,aa,SizeOf(aa)); //以下是数组传递到指针bb:=GetMemory(SizeOf(aa));Move(