c++复习6.类的组合、常成员、静态成员、深浅复制、内存泄漏(实验二、作业2)

实验二参考示例

一.实验目的

1.理解并掌握类的常对象的定义及访问方法;

2.理解并掌握类的常成员函数的含义及使用方法

3.理解并掌握数组对象的含义及使用方法;

4.理解并掌握动态内存分配的原理和使用方法;

5.理解并掌握内存泄漏产生的原因及解决方法;

6.理解并掌握深复制和浅复制的区别和使用方法,深入理解自定义类的拷贝构造函数的必要性和意义;

7.理解并掌握类的继承和派生的方法和原理;

二. 实验内容

1.类的常对象的定义及访问方法

1.请根据要求,完成以下内容:

(1)定义一个class Point类,其中含有2个私有数据成员,分别是点的两个的坐标值:x,y;含有三个成员函数,分别是:int getX()(返回点的x坐标值),int getY()(返回点的y坐标值),double Dist()(计算两点间距离); 成员函数重载,分别为:分别为:double Dist()和double Dist()const, 并要求double Dist()const形式参数为常对象.

(2)主函数定义Point类的普通对象和常对象,以:Point myp1(1,1), myp2(4,5); Point p1(x1, y1), Point p2(x2, y2);进行测试(其中,myp1(1,1)和myp2(4,5)在主函数中定义为常对象,p1(x1,y1)和p2(x2,y2)定义为一般的对象,可调用默认值构造,也可自己给值),分别输出myp1(1,1), myp2(4,5)和p1(x1, y1)和p2(x2, y2)两点间距离。

给出以上程序的完整源代码,并粘贴运行结果截图。

#include <iostream>
#include <cmath>
using namespace std;
class Point {
public:
	Point(int xx, int yy) { x = xx, y = yy; }
	int getX()const;//必须声明常成员函数,否则常对象无法访问 
	int getY()const;//同上 
	double Dis(Point p);
	double Dis(const Point p) const;
private:
	int x;
	int y;
};
inline int Point::getX()const {
	return x;
}
inline int Point::getY()const {
	return y;
}
double Point::Dis(Point p) {
	int xx = x - p.getX();
	int yy = y - p.getY();
	return sqrt(xx*xx + yy*yy);
}
double Point::Dis(const Point p)const {
	int xx = x - p.getX();
	int yy = y - p.getY();
	return sqrt(xx*xx + yy*yy);
}
int main() {
	const Point myp1(1, 1);
	const Point myp2(4, 5);
	cout << "常对象(1,1) and (4,5) Dis: " << myp1.Dis(myp2) << endl;
	cout << "下面开始构造一般对象" << endl;
	int x1, y1, x2, y2;
	cout << "x1 and y1:";
	cin >> x1 >> y1;
	cout << "x2 and y2:";
	cin >> x2 >> y2;
	Point  p1(x1, y1),p2(x2, y2);
	cout << "一般对象 Dis: " << p1.Dis(p2) << endl;
	system("pause");
}

运行结果截图:

2. 数组对象的定义及使用方法

2. 请根据要求,完成以下内容:

(1)请定义一个score类:私有数据成员有:学号,姓名,平时成绩,期末考试成绩,总评成绩;成员函数有:类的构造函数score()(自定义其构造形式),count()(计算总评成绩:按总评成绩=平时*0.4,期末成绩*0.6),ShowScore()(输出各个私有数据成员);

(2)主函数要求以不带初始化的对象数组和带初始化的静态对象数组,分别构造3个对象,并分别输出每个对象的私有数据。

(3)输出格式如下:201701101   Li Hongmei  90  80  84。

(备注:输出顺序为:学号 姓名 平时成绩,期末成绩,总评成绩)

给出程序源代码,并粘贴运行结果截图。

#include <iostream>
#include <cmath>
#include <string>
using namespace std;

class Score {
public:
	Score();
	Score(string xID, string xname, double sc1, double sc2);
	void count();
	void showScore();
private:
	string ID;
	string name;
	double daily_grade;//平时 
	double final_grade;//期末 
	double total_grade;//总评

};
Score::Score() {
	this->Score::Score("null", "null", 0, 0);
}
Score::Score(string xID, string xname, double sc1, double sc2) {
	ID = xID;
	name = xname;
	daily_grade = sc1;
	final_grade = sc2;

}
void Score::count() {
	total_grade = daily_grade*0.4 + final_grade*0.6;
}
void Score::showScore() {
	cout << ID << "   " << name
		<< "   " << daily_grade
		<< "   " << final_grade
		<< "   " << total_grade << endl;
}
int main() {
	int i;
	Score sc1[3];
	cout << "不带初始化的对象数组" << endl;
	for (i = 0; i<3; i++) {
		sc1[i].count();
		sc1[i].showScore();
	}
	cout << "\n带初始化的静态对象数组" << endl;
	static Score sc2[3] = {
		Score("201700001","Tomt",
		91,97),
		Score("201700002","Jack",
		83,95),
		Score("201700003","Mary",
		100,97),
	};
	for (i = 0; i<3; i++) {
		sc2[i].count();
		sc2[i].showScore();
	}
	system("pause");

}

运行结果截图:

3.请用动态分配数组实现上面的题目,给出源代码,并粘贴运行结果截图.

静态数组:(用指针数组来new)

静态数组:
#include <iostream>
#include <cmath>
#include <string>
using namespace std;

class Score {
public:
	Score();
	Score(string xID, string xname, double sc1, double sc2);
	void count();
	void showScore();
private:
	string ID;
	string name;
	double daily_grade;//平时 
	double final_grade;//期末 
	double total_grade;//总评

};
Score::Score() {
	this->Score::Score("null", "null", 0, 0);
}
Score::Score(string xID, string xname, double sc1, double sc2) {
	ID = xID;
	name = xname;
	daily_grade = sc1;
	final_grade = sc2;

}
void Score::count() {
	total_grade = daily_grade*0.4 + final_grade*0.6;
}
void Score::showScore() {
	cout << ID << "   " << name
		<< "   " << daily_grade
		<< "   " << final_grade
		<< "   " << total_grade << endl;
}
int main() {
	int i;
	Score *sc1[3];//也可以仿照教材P223页的例题6-17,设一个指针指向在堆中创建的有3个分量的一维数组
	cout << "不带初始化的对象数组" << endl;
	for (i = 0; i<3; i++) {
		sc1[i] = new Score();
		sc1[i]->count();
		sc1[i]->showScore();
	}
	cout << "\n带初始化的静态对象数组" << endl;
	static Score *sc2[3]= {
		new Score("201700001","Tomt",
		91,97),
		new Score("201700002","Jack",
		83,95),
		new Score("201700003","Mary",
		100,97),
	};
	for (i = 0; i<3; i++) {
		sc2[i]->count();
		sc2[i]->showScore();
	}
	//释放资源
	delete [] *sc1;
	delete [] *sc2;
	system("pause");
}

运行结果截图:

动态数组:(直接new)

#include <iostream>
#include <cmath>
#include <string>
using namespace std;
class Score {
public:
	Score();
	Score(string xID, string xname, double sc1, double sc2);
	void count();
	void showScore();
private:
	string ID;
	string name;
	double daily_grade;//平时 
	double final_grade;//期末 
	double total_grade;//总评
};
Score::Score() {
	this->Score::Score("null", "null", 0, 0);
}
Score::Score(string xID, string xname, double sc1, double sc2) {
	ID = xID;
	name = xname;
	daily_grade = sc1;
	final_grade = sc2;
}
void Score::count() {
	total_grade = daily_grade * 0.4 + final_grade * 0.6;
}
void Score::showScore()
{
	std::cout  << ID << "   " << name
		<< "   " << daily_grade
		<< "   " << final_grade
		<< "   " << total_grade << endl;
}
int main() {
	
	Score* p = new Score[3]{ Score("201700001","Tomt",
		91,97),Score("201700002","Jack",
		83,95),Score("201700003","Mary",
		100,97), };//也可以仿照教材P223页的例题6-17,设一个指针指向在堆中创建的有3个分量的一维数组
	cout << "对象数组: " << endl;
	for (int i = 0; i < 3; i++) {
		p[i].count();
		p[i].showScore();
	}
	cout << "\n带初始化的静态对象数组" << endl;
	//释放资源
	delete[] p;
	system("pause");
}

运行结果截图:

4.关于深复制和浅复制

1.请分析下列程序的运行结果,回答问题:

#include <iostream>

#include <cstring>

using namespace std;

class CA

{public:

    CA(int b,char* cstr)

    {a=b;

    str=new char[b];

    strcpy(str,cstr);

cout << "构造成功"<<endl;}

void Show()

 {cout<<"构造的字符串为:"<<str<<endl;

  cout<<"构造的字符串地址为:"<<(int)str<<endl;

 }

 ~CA(){delete str;}

 private:

    int a;

    char *str;};

int main()

{CA A(10,"Hello!");

 A.Show();

 CA B=A;

 B.Show();

 return 0; }

(1)根据程序的运行结果,推出系统默认的拷贝构造函数是如何编写的?

答:(更正答案)

(2)上述程序实现的是浅复制还是深复制?简述两者的区别,并分析对象A的str和对象B的str内存地址相同的原因。

答:因为:原程序没有构造自己的拷贝构造函数,当原程序执行语句:CA B=A;时,调用的是编译器提供的默认的拷贝构造函数,编译器实现的是浅拷贝。即:编译器执行的浅拷贝的构造函数是: CA(const CA& A){a=A.a;str=A.str; },编译器在构造B对象时,传递给B对象str的是A对象str的地址,所以,二者的地址相同。

(3)浅复制在哪种情况下会带来哪些问题?应该如果解决?

答:同(2)。

(4)上述程序会造成内存泄漏吗?如果存在,请分析内存泄漏会在哪一步发生?

答:

(5)请给出自定义深复制构造函数后的完整程序源代码,并粘贴运行结果截图。

答:源代码:

#include <iostream>
#include <cstring>
using namespace std;
class CA
{public:
    CA(int b,char* cstr)
    {a=b;
    str=new char[b];
    strcpy(str,cstr);
    cout << "构造成功"<<endl;}
    CA(const CA& C)
    {a=C.a;str=new char[a]; //深拷贝
    if(str!=0)
        {strcpy(str,C.str);
        cout << "拷贝构造成功"<<endl;}}
 void Show()
 {cout<<"构造的字符串为:"<<str<<endl;
  cout<<"构造的字符串地址为:"<<(int)str<<endl;
 }
 ~CA(){delete str;}

 private:
    int a;
    char *str;};
int main()
{CA A(10,"Hello!");
 A.Show();
 CA B=A;
 B.Show();
 return 0;}

5.关于拷贝复制构造函数

5.请阅读下列程序,然后回答问题:

#include<iostream>

using namespace std;

class Rect

{

public:

    Rect()

    {

     count++;

    }

    ~Rect()

    {

     count--;

    }

    static int getCount()

    {

     return count;

    }

private:

    int width;

    int height;

    static int count;

};

int Rect::count=0;

int main()

{

    Rect rect1;

    cout<<"The count of Rect:"<<Rect::getCount()<<endl;

    Rect rect2(rect1);

    cout<<"The count of Rect:"<<Rect::getCount()<<endl;

    return 0;

}

(1)  上述程序的本意是统计矩形的个数,但从实际运行结果看,并没有达到这个目的,请分析原因。

答:1)原程序没有定义自己的拷贝构造函数,主函数在执行语句:Rect rect2(rect1);时,调用的系统默认的拷贝构造函数,而系统默认的拷贝构造函数,只是对非静态成员进行简单的复制,并不会对统计对象个数的静态成员counter做任何处理,所以,counter仍然保持构造拷贝复制对象之前的值,没有随着对象的增加而增加,没有达到预期的目的。

(2)修改上述程序,使其能够正确输出已经创建的矩形数量。请给出源代码完整程序,并粘贴运行结果截图。

答:

#include<iostream>
using namespace std;
class Rect
{
public:
    Rect()
    {
        count++;
    }
    Rect(const Rect& r)
    {
        width=r.width;
        height=r.height;
        count++;
    }
    ~Rect()
    {
        count--;
    }
    static int getCount()
    {
        return count;
    }
private:
    int width;
    int height;
    static int count;
};
int Rect::count=0;
int main()
{
    Rect rect1;
    cout<<"The count of Rect:"<<Rect::getCount()<<endl;
    Rect rect2(rect1);
    cout<<"The count of Rect:"<<Rect::getCount()<<endl;
    return 0;
}

运行结果截图:

 

6.关于类的继承与派生

6.下面的程序已经定义了一个基类Shape,请按要求完成以下内容:

#include <iostream>

using namespace std;

class Shape

{

public:

    Shape(){}

    ~Shape(){}

    virtual float getArea() { return -1; }

};

class Circle : public Shape

//定义Circle类

{

};

class Rectangle : public Shape

//定义Rectangle类

{

}

class Square : public Rectangle

//定义Aquare类

{

};

int main()

{

    Shape * sp;

    sp = new Circle(5);

    cout << "The area of the Circle is " << sp->getArea () << endl;

    delete sp;

    sp = new Rectangle(4, 6);

    cout << "The area of the Rectangle is " << sp->getArea() << endl;

    delete sp;

    sp = new Square(5);

    cout << "The area of the Square is " << sp->getArea() << endl;

    delete sp;

    return 0;

}

(1)在此基础上派生出Rectangle和Circle,二者都有getArea()函数计算对象的面积;

(2)使用Rectangle类创建一个派生类Square;

请给出上述程序的完整源程序,并粘贴运行结果截图。

答:

#include <iostream>
using namespace std;
class Shape
{
public:
    Shape(){}
    ~Shape(){}
    virtual float getArea() { return -1; } 
};

class Circle : public Shape
{
public:
    Circle(float radius):itsRadius(radius){}
    ~Circle(){}
    float getArea() { return 3.14 * itsRadius * itsRadius; }
private:
    float itsRadius;
};

class Rectangle : public Shape
{
public:
    Rectangle(float len, float width): itsLength(len), itsWidth(width){};
    ~Rectangle(){};
    virtual float getArea() { return itsLength * itsWidth; }
    virtual float getLength() { return itsLength; }
    virtual float getWidth() { return itsWidth; }
private:
    float itsWidth;
    float itsLength;
};

class Square : public Rectangle
{
public:
       Square(float len);
       ~Square(){}
};

Square::Square(float len):
    Rectangle(len, len)
{
}

int main()
{
    Shape * sp;

	sp = new Circle(5);
	cout << "The area of the Circle is " << sp->getArea () << endl;
	delete sp;
	sp = new Rectangle(4, 6);
	cout << "The area of the Rectangle is " << sp->getArea() << endl;
	delete sp;
	sp = new Square(5);
	cout << "The area of the Square is " << sp->getArea() << endl;
	delete sp;
	return 0;
}

运行结果截图:

7.关于继承类成员函数的调用顺序

7.下列程序已经定义了一个哺乳动物类Mammal,再由此派生出狗类Dog,定义一个Dog类的对象,观察基类和派生类的构造函数与析构函数的调用顺序。根据下面程序代码和运行结果截图,请将哺乳动物类Mammal和其派生的狗类Dog的构造函数补充完整,给出程序的完整源代码,并粘贴运行结构截图。

#include <iostream>

using namespace std;

enum myColor {

    BLACK, WHITE

};

class Mammal {

public:

    // constructors

    Mammal();

    ~Mammal();

    //accessors

    int getAge() const {

        return itsAge;

    }

    void setAge(int age) {

        itsAge = age;

    }

    int getWeight() const {

        return itsWeight;

    }

    void setWeight(int weight) {

        itsWeight = weight;

    }

    //Other methods

    void speak() const {

        cout << "Mammal sound!\n";

    }

protected:

    int itsAge;

    int itsWeight;

};

class Dog: public Mammal {

public:

    Dog();

    ~Dog();

    myColor getColor() const {

        return itsColor;

    }

    void setColor(myColor color) {

        itsColor = color;

    }

    void wagTail() {

        cout << "Tail wagging...\n";

    }

private:

    myColor itsColor;

};

//下面请将Mammal类的构造函数补充完整

Mammal::Mammal() :

    {   }

Mammal::~Mammal() {

    cout << "Mammal destructor...\n";

}

//下面请将Dog类的构造函数补充完整

Dog::Dog() : {  }

Dog::~Dog() {

    cout << "Dog destructor...\n";

}

int main() {

    Dog jack;

    jack.speak();

    jack.wagTail();

    cout << " jack is " << jack.getAge() << " years old\n";

    return 0;

}

   

请给出完整源代码和运行结果截图。

答:

 #include <iostream>
using namespace std;
enum myColor {
	BLACK, WHITE
};
class Mammal {
public:
	// constructors
	Mammal();
	~Mammal();

	//accessors
	int getAge() const {
		return itsAge;
	}
	void setAge(int age) {
		itsAge = age;
	}
	int getWeight() const {
		return itsWeight;
	}
	void setWeight(int weight) {
		itsWeight = weight;
	}

	//Other methods
	void speak() const {
		cout << "Mammal sound!\n";
	}

protected:
	int itsAge;
	int itsWeight;
};

class Dog: public Mammal {
public:
	Dog();
	~Dog();

	myColor getColor() const {
		return itsColor;
	}
	void setColor(myColor color) {
		itsColor = color;
	}

	void wagTail() {
		cout << "Tail wagging...\n";
	}

private:
	myColor itsColor;
};

Mammal::Mammal() :
	itsAge(1), itsWeight(5) {
	cout << "Mammal constructor...\n";
}

Mammal::~Mammal() {
	cout << "Mammal destructor...\n";
}
Dog::Dog() :
	itsColor(WHITE) {
	cout << "Dog constructor...\n";
}

Dog::~Dog() {
	cout << "Dog destructor...\n";
}
int main() {
	Dog jack;
	jack.speak();
	jack.wagTail();
	cout << " jack is " << jack.getAge() << " years old\n";

	return 0;
}

运行结果截图:

作业2-答案

1.下列程序期望的运行结果为:

t1.m_num:1

t2.m_num:1

(1)运行下列程序,给出运行结果截图;

(2)分析程序没有得到预期结果的原因;

(3)尝试给出一种以上解决方案,使程序能够输出期望值;

(4)由上述的分析和尝试,可以得出哪些结论;

#include <iostream>

using namespace std;

class Test

{

public:

    int m_num=1;

};

Test* getObj1()

{

Test t1,*p1=&t1; 

return p1;

}

Test& getObj2()

{

Test t2, & p2 = t2; 

return p2;

}

int main()

{

    Test* t1 = getObj1();  

    Test& t2 = getObj2();

    cout << "t1.m_num: " << (*t1).m_num << endl;

    cout << "t2.m_num: " << t2.m_num << endl;

    return 0;

};

答:

(1)运行结果截图:

(2)原因:

函数getObj1()和getObj2()返回的均是指向各自函数中创建的局部对象的地址(引用的底层实现为指针)。局部对象创建于栈中,随着函数调用的结束,栈空间被释放,即:该空间会被系统标记为可用,可被系统分配给其它进程使用。因此,主函数中的指针变量t1和引用变量t2,就指向了一个已经被标记为可用的内存空间,该空间会被系统赋给一个随机值。所以,程序得不到期望的运行结果,而且每次运行的结果也会不同

(3)解决方案:

① 将函数中的局部对象,改为静态局部对象,返回静态局部对象的指针和引用;

Test* getObj1()
{
    static Test t1;  //设置为静态局部变量
    Test * p1 = &t1;
    return p1;
}

Test& getObj2()
{
    static Test t2; //设置为静态局部变量 
    Test & p2 = t2;
    return p2;
}

运行结果截图:

② 将函数中的局部对象,改为全局对象,返回全局对象的指针和引用:

class Test
{
public:
    int m_num = 1;
};
Test t1;  //设置为全局变量
Test t2; //设置为全局变量 

运行结果截图:

③ 在堆中创建对象,返回堆对象的指针和引用(注意在调用函数中,需要销毁指针所指向的堆空间,否则,会造成内存泄漏;调用函数中,引用对象所引用的堆空间,编译器会自动调用对象的析构函数进行析构):

Test* getObj1()
{
    Test* p1 = new Test; //在堆中申请空间
    return p1;
}

Test& getObj2()
{
    Test *p2 = new Test; //在堆中申请空间
    Test & p3 = *p2;
    return p3;
}

运行结果截图:

④用vector实现

(4)结论:

① 函数返回值为数值时,可以返回函数内部定义的普通局部变量(也称为自动变量);

② 函数返回值为指针或引用时,确定是否允许返回局部指针或引用变量,不在于该指针或引用变量是否为局部指针或局部引用变量,而在于该指针或引用所指向或所引用的对象的生命周期,是否长于其所在的函数;若该指针或引用所指向或所引用的对象的生命周期,长于其所在的函数,即为合法;

2.下列程序期望的运行结果为:1000

(1)程序能否编译通过?若不能通过,说明原因。

(2)修改程序,使其能够输出期望值1000。

(3)在主函数return 0;语句之前,a的值是多少。

#include <iostream>

using namespace std;

int& done()

{

    static int a = 10;

    return a;

}

int main()

{

    int& ret = done();

    done () = 1000;

    cout << a << endl;

return 0;

    }

答:

(1)不能。done()函数中的变量a,虽然是静态变量,其生命周期大于其所在的函数;但是a是局部变量,在其所在的函数外部,不可见,不能被访问。

(2)修改后的程序如下:

#include <iostream>
using namespace std;
int& done()
{
	static int a = 10;
	return a;
}
int main()
{
	int& ret = done();
	done () = 1000; 
	//cout << a << endl;
	cout << done() << endl;
return 0;
}

(3)主函数中的“done () = 1000; ”语句,实际是给a赋值,所以a的值是1000。

3.下列关于常引用的程序:

(1)指出下列程序中的错误。

(2)说明常引用的实质作用及其作为函数形参的实质作用。

void test()

{

      int a = 100;

      const int& aRef = a;

      aRef = 200;

      a = 100;

      cout << "a:" << a << endl;

      cout << "aRef:" << aRef << endl;

}

答:(1)

void test()

{

    int a = 100;

    const int& aRef = a;

    //aRef = 200; 常引用不能修改其值。

    a = 100;

    cout << "a:" << a << endl;

    cout << "aRef:" << aRef << endl;

}
(2)常引用作用的实质是:限制了引用变量的权限,即:不能通过常引用变量改变被引用变量的值;采用常引用作为函数形参,实质是:在函数中不能对实参进行改变。

4.下列关于右值引用和移动构造函数的程序:

(1)分别给出允许编译器优化和禁止编译器优化的程序运行结果,并分析结果原因。

(2)说明C++11引入右值引用和移动构造函数的目的。

#include <iostream>

struct Foo {

    ~Foo() { std::cout << "destruction" << std::endl; }

};

Foo FooFactory() {

    return Foo();

}

int main() {

    std::cout << "before copy constructor..." << std::endl;

    Foo foo1 = FooFactory();

    std::cout << "after copy constructor..." << std::endl << std::endl;

    Foo&& foo2 = FooFactory();

    std::cout << "life time ends!" << std::endl << std::endl;

    return 0;

}

答:(1)

VS2022编译器优化后的运行结果:

未优化的运行结果(之一:clang编译器)

原因分析(其它运行结果,以本地编译器为准,自行分析):

此程序可以从析构函数的执行次数,来判断复制构造函数和移动构造函数是否被调用执行。设置断点,根据程序单步运行过程,具体分析见程序的注释部分:

#include <iostream>

struct Foo {

    ~Foo() { std::cout << "destruction" << std::endl; }

};

Foo FooFactory() {

    return Foo(); //VS022:优化前,默认复制构造函数被调用,在主函数中被复制构造了一个临时对象,之后Foo()函数生成的匿名对象销毁,析构函数被调用一次;优化后,默认复制构造没有被调用,析构函数也没有被调用,而是主函数直接按照返回值,由主函数调用默认构造函数构造了fool对象。

}

int main() {

    std::cout << "before copy constructor..." << std::endl;

    Foo foo1 = FooFactory();//VS2022:优化前,默认复制构造函数被调用,将临时对象复制一份赋给fool对象,之后临时对象销毁,析构函数被调用一次;优化后,默认复制构造函数没有被调用,析构函数也没有被调用,因为FooFactory()函数返回值并没有生成临时对象,而是FooFactory()函数直接将返回值放到了主函数构造对象的地址处,由主函数调用默认构造函数构造了fool对象。

    std::cout << "after copy constructor..." << std::endl << std::endl;

    Foo&& foo2 = FooFactory(); //VS2022:优化前,因为foo2为右值引用对象,主函数会自动调用默认移动构造函数,按照FooFactory()函数返回的临时对象,来构造foo2对象,之后,临时对象销毁,析构函数被调用一次,默认复制构造函数没有被调用,调用的是默认移动构造函数;优化后,默认复制构造函数没有被调用,默认移动构造函数也没有被调用,析构函数也没有被调用,因为FooFactory()函数返回值并没有生成临时对象,而是FooFactory()函数直接将返回值放到了主函数对象foo2的地址处,由主函数调用默认构造函数构造了foo2对象。

    std::cout << "life time ends!" << std::endl << std::endl;

    return 0;

}

(2)右值引用是对将亡值的引用,目的是获取匿名对象(将亡值)的地址,为能够应用移动复制做准备。

移动构造函数在构造右值引用对象时被调用,构造时不再申请新的空间,而是进行地址赋值,进行浅复制,进而节省了复制的时间,提高了复制效率。

  • 18
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值