C++ 对象使用过程中调用了哪些方法

示例1

#include <iostream>
using namespace std;

class Test
{
public:
  Test(int a = 10) :ma(a)
  {
    cout << "Test(int)" << endl;
  }
  ~Test()
  {
    cout << "~Test()" << endl;
  }
  Test(const Test &t) :ma(t.ma)
  {
    cout << "Test(const Test&)" << endl;
  }
  Test& operator=(const Test &t)
  {
    cout << "operator=" << endl;
    ma = t.ma;
    return *this;
  }
private:
  int ma;
};

int main() {

  cout << "1.Test t1;" << endl;
  Test t1;

  cout << "\n2.Test t2(t1)" << endl;
  Test t2(t1);//拷贝构造函数

  cout << "\n3.Test t3 = t1;" << endl;
  Test t3 = t1;//拷贝构造函数

  cout << "\n4.Test t4 = Test(20);" << endl;
  /*
  C++编译器对于对象构造的优化:用临时对象生成新对象的时候,临时对象
  就不产生了,直接构造新对象就可以了
  */
  Test t4 = Test(20);//和Test t4(20);没有区别的! 仅调用一次默认构造函数


  cout << "\n5. t4 = t2;" << endl;
  t4 = t2;调用赋值函数,因为t4原本已存在 

  cout << "\n6 t4 = Test(20);" << endl;
  t4 = Test(20);// 显式生成临时对象,临时对象生成后,给t4赋值,出语句后,临时对象析构 (默认构造函数,赋值运算符,析构函数)


  cout << "\n7.t4 = (Test)30;" << endl;
  /************************************************************************/
  /* 把其他类型转成类类型的时候,编译器就看这个类类型
  有没有合适的构造函数 把整型转成Test,就看这个类类型有没有
  带int类型参数的构造函数 ,有,就可以显式生成临时对象,然后
  赋值给t4 出语句后,临时对象析构                                                                     
  */
  /************************************************************************/
  t4 = (Test)30;//把30强转成Test类型int->Test(int)  同t4 = Test(20);

  cout << "\n8.t4 =30;" << endl;
  t4 = 40;//隐式生成临时对象,然后赋值给t4,出语句后,临时对象析构  同7



  cout << "\n9 Test *p = &Test(40);" << endl;
  Test *p = &Test(40);//指针指向临时对象,这个临时对象肯定是要生成的
//然后p指向这个临时对象的地址
//出语句后,临时对象析构 
//此时p指向的是一个已经析构的临时对象,p相当于野指针了

  cout << "\n10 const Test &ref = Test(50);" << endl;
  const Test &ref = Test(50);//引用一个临时对象,这个临时对象也是要生成的
  //出语句后,临时对象不析构,因为引用相当于是别名,临时对象出语句析构是因为没有名字 
//用引用变量引用临时对象是安全的,临时对象就是有名字了,临时对象的生存周期就变成引用变量的
//生存周期了。引用变量是这个函数的局部变量,return完,这个临时对象才析构 


  cout << "\nfinish" << endl;
  return 0;
}



示例2

#include <iostream>
using namespace std;

class Test
{
public:
  //因为a,b有默认值所以构造有3种方式:
  //Test() Test(10) Test(10, 10)
  Test(int a = 5, int b = 5)//构造函数 
    :ma(a), mb(b)
  {
    cout << "Test(int, int):" << ma << "," << mb << endl;
  }
  ~Test()//析构函数 
  {
    cout << "~Test():" << ma << "," << mb << endl;
  }
  Test(const Test &src)//拷贝构造函数 
    :ma(src.ma), mb(src.mb)
  {
    cout << "Test(const Test&)" << endl;
  }
  void operator=(const Test &src)//赋值函数 
  {
    ma = src.ma;
    mb = src.mb;
    cout << "operator=" << endl;
  }
private:
  int ma;
  int mb;
};


Test t1(10, 10);//在mian函数之前构造,在main函数结束后释放,存储在.data段

int main() {

  cout << "\n---------------------------main()" << endl;
  
  cout << "\n 1.Test t2(20,20); " << endl;
  Test t2(0,0);//默认构造函数


  cout << "\n 2.Test t3 = t2" << endl;
  Test t3 = t2;//拷贝构造函数


  cout << "\n 3.Test t3 = t2" << endl;
  static Test t4 = Test(30, 30);//第一次运行到它才初始化

  cout << "\n 4 t2 = (Test)(50, 50);" << endl;
    //(50,50)是逗号表达式,(表达式1,表达式2,表达式n)
  //(50,50)的最后的结果是最后一个表达式n的结果 50
  //(50, 50) =  (Test)50;
  t2 = (Test)(50, 50);//Test(int,int) operator= 出语句调用~Test()

  cout << "\n 5  Test* p1 = new Test(70, 70);" << endl;
  Test* p1 = new Test(70, 70);// Test(int,int) 要调用delete才析构对象

  cout << "\n 6  Test* p2 = new Test[2];" << endl;
  Test* p2 = new Test[2];//  Test(int,int) Test(int,int) 要调用delete才析构对象

  cout << "\n 7  Test* p3 = &Test(80, 80);" << endl;
  Test* p3 = &Test(80, 80);// Test(int,int) 出语句调用~Test()

  cout << "\n 8  const Test& p4 = Test(90, 90);" << endl;
  const Test& p4 = Test(90, 90);//Test(int,int)

  delete p1;//~Test()
  delete[]p2;// ~Test() ~Test()

  cout << "\n---------------------------finish" << endl;
  return 0;
}

Test t5(100, 100);//Test(int, int)

 

 示例3 

#include <iostream>

using namespace std;

class Test
{
public:
  //有默认值,可以有2种构造方式:Test()  Test(20)
  Test(int data = 10) :ma(data)
  {
    cout << "Test(int):" <<  ma <<  endl;
  }
  ~Test()
  {
    cout << "~Test()" << ma <<  endl;
  }
  Test(const Test &t) :ma(t.ma)
  {
    cout << "Test(const Test&)" << endl;
  }
  void operator=(const Test &t)
  {
    cout << "operator=" << endl;
    ma = t.ma;
  }
  int getData()const { return ma; }
private:
  int ma;
};

Test GetObject(Test t)
{
  cout << "\n----------------GetObject1 \n";
  int val = t.getData();
  Test tmp(val);
  cout << "\n----------------GetObject2 \n";
  return tmp;
}
int main()
{
  Test t1;//1、调用带整型参数的构造函数 
  Test t2;//2、调用带整型参数的构造函数
  
  /*
  (1)实参传递给形参 :调用Test(const Test&) 拿t1拷贝构造形参t
   (2) 调用Test(int)的构造,构造tmp对象
   (3) return tmp;tmp和t2是两个不同函数栈帧上的对象,是不能直接进行赋值的 GetObject函数完成调用时
      tmp对象作为局部对象就析构了 ,为了把返回值带出来, 在return tmp;这里,首先要在main函数栈帧
      上构建一个临时对象,目的就是把tmp对象带出来

  (4) 调用 Test(const Test&),tmp拷贝构造main函数栈帧上的临时对象
  (5) 出 GetObject作用域,tmp析构
  (6) 形参t对象析构
  (7) operator =,把main函数刚才构建的临时对象赋值给t2,临时对象没名字,出了语句就要析构
  (8) 把main函数刚才构建的临时对象析构
  (9) main函数结束,t2析构
  (10) t1析构

  */

  cout << "\n----------------main GetObject1 \n";
  t2 = GetObject(t1);//函数调用
  cout << "\n----------------main GetObject2 \n";
  return 0;
}


 总结三条对象优化的规则

  1. 函数参数传递过程中,对象优先按引用传递,这样可以省去一个形参t的拷贝构造调用,形参没有构建新的对象,出作用域也不用析构了,所以不要按值传!
  2. 函数返回对象的时候,应该优先返回一个临时对象,而不要返回一个定义过的对象
  3. 接收返回值是对象的函数调用的时候,优先按初始化的方式接收,不要按赋值的方式接收

优化1:没有t1的拷贝构造,形参t没有新的对象,出作用域也不用析构。
省去了形参t的拷贝构造和形参t的析构

 优化2:函数返回对象的时候,应该优先返回一个临时对象,而不要返回一个定义过的对象

3、接收返回值是对象的函数调用的时候,优先按初始化的方式接收,不要按赋值的方式接收

 函数返回值临时对象给t2初始化!用这个临时对象拷贝构造同类型的新对象t2。C++编译器会进行优化,这个main函数栈帧上的临时对象都不产生了,直接构造t2对象。也就是return Test(val);直接构造t2对象了

Test t2= GetObject(t1);在汇编上,除了把t1的地址传进去,还把t2的地址也传进去了,也压到函数栈帧上,所以return Test(val);就可以取到t2的地址,就知道在哪块内存上构造一个名为t2的对象。

 

#include <iostream>

using namespace std;

class Test
{
public:
  //有默认值,可以有2种构造方式:Test()  Test(20)
  Test(int data = 10) :ma(data)
  {
    cout << "Test(int):" <<  ma <<  endl;
  }
  ~Test()
  {
    cout << "~Test()" << ma <<  endl;
  }
  Test(const Test &t) :ma(t.ma)
  {
    cout << "Test(const Test&)" << endl;
  }
  void operator=(const Test &t)
  {
    cout << "operator=" << endl;
    ma = t.ma;
  }
  int getData()const { return ma; }
private:
  int ma;
};

Test GetObject(const Test &t)
{
  cout << "\n----------------GetObject1 \n";
  int val = t.getData();
 // Test tmp(val);
  cout << "\n----------------GetObject2 \n";
  return Test(val);
}
int main()
{
  Test t1;//1、调用带整型参数的构造函数 


  cout << "\n----------------main GetObject1 \n";
  Test t2 = GetObject(t1);//函数调用
  cout << "\n----------------main GetObject2 \n";
  return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值