精华内容
下载资源
问答
  • 临时对象

    2018-12-03 15:27:19
    临时对象分为显式生成和隐式生成 一般没有引用时,临时对象在表达式结束后生命周期结束。 显式生成临时对象 显式生成即在生成临时对象时注明临时对象的类型 即 Node n1;  n1=Node(10);   隐式生成临时对象 ...

    临时对象分为显式生成和隐式生成

    一般没有引用时,临时对象在表达式结束后生命周期结束。

    • 显式生成临时对象

    显式生成即在生成临时对象时注明临时对象的类型

    即 Node n1;

        n1=Node(10);

     

    • 隐式生成临时对象

    隐式生成即在生成临时对象时并不注明对象的类型,需要编译器的推算。

     即 Node n1;

         n1=10;

    显式生成临时对象与隐式生成临时对象的区别

    显式生成的临时对象时变量,隐式生成的临时对象是常量

    例:

    #include<iostream>
    
    class Node{
    public:
    	Node(int ma=0)
    	{
    		this->ma=ma;
    		std::cout<<"Node(int ma=0)"<<std::endl;
    	}
    	~Node()
    	{
    		std::cout<<"~Node()"<<std::endl;
    	}
    	Node(const Node& rhs)
    	{
    		std::cout<<"Node(const Node& rhs)"<<std::endl;
    	}
    	Node& operator=(const Node& rhs)
    	{
    		std::cout<<"Node& operator=(Node& rhs)"<<std::endl;
    		return *this;
    	}
    	
    	void Show()
    	{
         	std::cout<<"void show()   "<<std::endl;
    	}
    private:
    	int ma;
    };

    使用Node类来进行测试

    显式生成临时对象:

    int main()
    {
          Node n ;
    	std::cout<<"--------------------"<<std::endl;
    	 n=Node(10);
    	std::cout<<"--------------------"<<std::endl;
    	return 0;
    }

    运行结果:

    我们可以看出,可以使用普通对象指针指向临时对象

    并且在n=Node(10);这一条语句中调用了构造函数、运算符重载函数和析构函数,

    说明临时对象的生存周期在表达式结束就结束。

    隐式生成临时对象:

    将运算符重载函数的形参改为Node &rhs 而非const Node &rhs

    int main()
    {
    	
    	std::cout<<"--------------------"<<std::endl;
    	 Node &n = 10;
    	std::cout<<"--------------------"<<std::endl;
    	return 0;
    }

    程序提示错误,

    将运算符重载函数的形参改回const Node &rhs

    运行结果:

    我们可以看出只有常引用能够引用隐式生成的临时对象.

     

    临时对象的优化:

    1.

    例:

    int main()
    {
         std::cout<<"+++++++++++"<<std::endl;
    	 Node n1=Node(10);
    	std::cout<<"++++++++++++"<<std::endl;
    	std::cout<<"--------------------"<<std::endl;
    	 Node n2=20;
    	std::cout<<"--------------------"<<std::endl;
    	return 0;
    }

    通过上面的知识我们知道Node n1=Node(10) 和 Node n2=20;

    都应该生成一个临时对象,但从程序的运行接过来看,并没有生成临时对象。

    因为临时对象的目的如果是为了生成新对象,以生成临时对象的的方式生成新对象。

    即Node n1(10);和 Node n2(20);直接生成了新对象而没有生成临时对象再调用拷贝构造函数生成新对象

    2.

    例:

    int main()
    {
         std::cout<<"+++++++++++"<<std::endl;
    	 Node &n1=Node(10);
    	std::cout<<"++++++++++++"<<std::endl;
    	std::cout<<"--------------------"<<std::endl;
    	 const Node &n2=20;
    	std::cout<<"--------------------"<<std::endl;
    	return 0;
    }

    从上面的知识我们知道,临时变量的生存周期在表达式结束就结束

    但从程序的运行结果我们可以看出,在引用变量引用临时对象后,临时对象的生存周期发生了改变。

    因为引用能提升临时对象的生存周期,把临时对象的生存周期提升到和引用变量相同的生存周期。

    执行 Node &n1=Node(10);后临时对象的生存周期被提升到和n1的生存周期相同,

    n1的生存周期到main函数退栈时结束,此时临时变量的生存周期也就结束,调用析构函数。

     const Node &n2=20;与n1相同。

     

    • 返回值为类类型,通过临时对象带出,而并非将局部对象直接返回

    例:

    #include<iostream>
    
    class Node{
    public:
    	Node(int ma=0)
    	{
    		this->ma=ma;
    		std::cout<<this<<"           Node(int ma=0)"<<std::endl;
    	}
    	~Node()
    	{
    		std::cout<<this<<"            ~Node()"<<std::endl;
    	}
    	Node(const Node& rhs)
    	{
    		std::cout<<this<<"          Node(const Node& rhs)            "<<&rhs<<std::endl;
    	}
    	Node& operator=(const Node& rhs)
    	{
    		std::cout<<"Node& operator=(const Node& rhs)"<<std::endl;
    		return *this;
    	}
    	
    	void Show()
    	{
         	std::cout<<"void show()   "<<std::endl;
    	}
    private:
    	int ma;
    };
    
    
    
    Node get(Node &rhs)
    {
    	std::cout<<"++++++++"<<std::endl;
    	Node tmp;
    	std::cout<<"++++++++"<<std::endl;
    	return tmp;
    }
    int main()
    {
    	Node n1;
    	Node n2;
    	std::cout<<"--------------"<<std::endl;
        n1=get(n2);
    	std::cout<<"--------------"<<std::endl;
    	return 0;
    }
    

    运行结果: 

    从运行结果和代码对比来看,006FFBF4 即为get()函数中对象tmp,

    但tmp在调用析构函数前调用了拷贝构造函数用tmp生成了临时对象006FFC38,将临时变量返回,而并非将局部对象返回(局部对象在函数退栈时就销毁)

    在n1=get(n2)表达式结束后,临时变量006FFC38才销毁。

     

    注意:

    #include<iostream>
    
    
    class CGoods
    {
    public:
    	CGoods(char* name, float price, int amount)
    	{
    		std::cout << this << " :CGoods::CGoods(char*,float, int)" << std::endl;
    		mname = new char[strlen(name) + 1]();
    		strcpy(mname, name);
    		mprice = price;
    		mamount = amount;
    	}
    	CGoods(int amount)
    	{
    		std::cout << this << " :CGoods::CGoods(int)" << std::endl;
    		mname = new char[1]();
    		mamount = amount;
    	}
    	CGoods()
    	{
    		std::cout << this << " :CGoods::CGoods()" << std::endl;
    		mname = new char[1]();
    	}
    	~CGoods()
    	{
    		std::cout << this << " :CGoods::~CGoods()" << std::endl;
    		delete[] mname;
    		mname = NULL;
    	}
    	CGoods(const CGoods& rhs)
    	{
    		std::cout << this << " :CGoods::CGoods(const CGoods&)" << std::endl;
    		mname = new char[strlen(rhs.mname) + 1]();
    		strcpy(mname, rhs.mname);
    		mprice = rhs.mprice;
    		mamount = rhs.mamount;
    	}
    	CGoods& operator=(const CGoods& rhs)
    	{
    		std::cout << this << " :CGoods::operator=(const CGoods&)" << std::endl;
    		if (this != &rhs)
    		{
    			delete[] mname;
    			mname = new char[strlen(rhs.mname) + 1]();
    			strcpy(mname, rhs.mname);
    			mprice = rhs.mprice;
    			mamount = rhs.mamount;
    		}
    		return *this;
    	}
    private:
    	char* mname;
    	float mprice;
    	int mamount;
    };
    
    
    int main()
    {
    	CGoods good;
    	good = (CGoods)("good8",10.1, 20);
    	return 0;
    }
    

    我们在遇到good=(Goods)(good8",10.1,20);时要特别注意

    因为右操作数是一个逗号表达式(逗号表达式的结果为最后一项的值),再将逗号表达式的结果强转为Goods类型,调用一个参数的构造函数显式生成临时对象,再调用赋值运算符重载函数进行赋值

    即good=(Goods)20;

    而并非调用三个参数的构造函数显式生成临时对象,再调用赋值运算符重载函数进行赋值

    运行结果:

    展开全文
  • 临时对象

    2009-06-06 00:52:00
    //临时对象是在堆栈中形成的,析构函数执行后,但是对象仍在那个地方,而且你的指针还指向那里. //任何时候我们都可以通过指针来调用成员函数,即使是强制类型转换的也可以. //比如说这样 ((Point *)0)->f(); //上面的...

    //临时对象是在堆栈中形成的,析构函数执行后,但是对象仍在那个地方,而且你的指针还指向那里.
    //任何时候我们都可以通过指针来调用成员函数,即使是强制类型转换的也可以.
    //比如说这样 ((Point *)0)->f();

    //上面的解释:非成员函数,与普通的C全局函数一样,存放在代码段里,所以就像普通函数一样,所有Point类的对象或者指针都可以使用,
    #include<iostream>
    #include<string>
    using namespace std;

    class Point{
    public:
     Point() { cout<<"Point()"<<endl;}
     ~Point() { cout<<"~Point()"<<endl;}
     f() {cout<<"f()"<<endl;}
    };

    int main()
    {
       string* p=& string();  //临时对象,在将地址赋给P后随即析构,但P还指向原来的地址,但已经无效
       Point* p2=& Point();   //与上面的情况相同
       ((Point*)0)->f();
       p2->f();              
       return 0;
    }


    /*output*/
    /* Point()
       ~Point()
       f()
     */

     

    //通过析构函数我们可以释放资源,那么你再访问这些资源就会无效.
    //实例代码如下,程序会崩溃.
    //关键【资源】二字
    /*#include <iostream>
    #include <string>
    using namespace std;

    class Point{
    public:
        Point() { cout <<"Point()" <<endl;p="123";}
        ~Point() { cout <<"~Point()" <<endl;p=NULL;}
        void f() {cout <<"f()" <<endl;cout<<p<<endl;}
    private:
        char *p;
    };

    int main()
    {
        string* p=& string();
        Point* p2=& Point();
        p2->f();            
        return 0;
    }*/

    展开全文
  • 文章目录1、什么是临时对象 1、什么是临时对象 C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行时确实生成了这样的对象. ...

    1、什么是临时对象

    C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行时确实生成了这样的对象.
    通常出现在一下两种情况:
    展开全文
  • c++ 临时对象的来源

    2020-09-05 16:04:09
    大家可能对这个临时对象这个概念还不是很清楚,那么首先我们花一些时间来理解临时对象
  • 一、临时量与临时对象 临时量: 内置类型生成的临时量是常量(临时量,寄存器带出来)。 自定义类型生成的临时量是变量 ,在内存中。 隐式生成生成的临时量是常量 ,显式生成生成的临时量是变量 。 临时对象: ...
  • C++ 临时对象

    2019-08-11 21:42:57
    1、什么是临时对象?  swap方法中,常常定义一个temp对象,这个temp对象不是临时对象,而是局部对象。这里所说的临时对象是不可见的,在原代码中是看不到的。 2、为什么会产生临时对象?  a、客户期望的数据与...

    1、什么是临时对象?

      swap方法中,常常定义一个temp对象,这个temp对象不是临时对象,而是局部对象。这里所说的临时对象是不可见的,在原代码中是看不到的。

    2、为什么会产生临时对象?

      a、客户期望的数据与你提供的数据不一致,需要隐式类型转换,中间需要适配一下,建立一个临时对象。

      b、方法返回值,他是没有名字的,起到一个传递作用,方法内部的局部对象-->方法返回值-->主调方法中的接受对象。

      c、异常处理,分为两个过程:抛出异常,捕获异常。抛出异常相当于return 方法内的局部对象,外部要有一个匿名的临时对象接收。catch语句类似于调用方法,将临时对象传给catch语句。

    3、对于第一种情况,只有传值和传const引用,才有可能导致临时对象。传一般的引用不会,考虑:

      double d = 3.14;

      int &ri = d;

      double 与int 类型不一致,需要适配,会创建一个临时对象int temp,temp的值为5,然后把temp传递给ri,如果修改ri的内容,只会导致temp的内容发生变化,而不会改变d的内容,这与程序员的期望不一致,造成错觉。因此,编译器拒绝这种隐式类型转换。

      但是,如果是const引用,为什么可以呢?

      因为const承诺了不会修改内容,就不会出现上面的情况,给程序员造成错觉。

    4、只要有临时对象,就会出现构造方法和析构方法。因此要尽量避免临时对象。

    5、对于第一种情况,解决办法是:尽量不要发生转型。

    6、对于第二种情况,解决办法:

      a、避免返回对象,对于有些有返回值的方法,可以在主调方法中创建一个局部对象,把局部对象,传递引用给被调方法,在被调方法中修改局部对象的引用,不再需要返回值。

      b、对于必须返回对象的情况,让方法返回引用或者指针都是不合适的(引用:方法返回时,对象销毁了,引用指向的是垃圾;指针:客户,也就是主调方法需要负责内存的释放)。也就是说,无法消除返回对象。这种情况下,可以采用Constructor Arguments代替被调方法中的局部对象,不仅能够消除方法内的局部对像,还可以消除方法返回时的临时对象,这就是返回值优化(RVO = Return Value Optimization)。

    7、对于第三种情况,抛出异常类似于方法返回值的过程,抛出异常相当于return方法内的局部对象,外部需要一个匿名的临时对象接收,这个临时对象不能消除。同时捕获异常的catch(exception ex)类似于调用方法,为了避免再次copy构造对象,catch语句使用 reference

    转载于:https://www.cnblogs.com/nzbbody/p/3421861.html

    展开全文
  • 详解C++ 中的临时对象

    2020-12-16 19:29:36
    C++中临时对象(Temporary Object)又称无名对象。临时对象主要出现在如下场景。 1.建立一个没有命名的非堆(non-heap)对象,也就是无名对象时,会产生临时对象。 Integer inte= Integer(5); //用无名临时对象...
  • c++临时对象

    2018-11-09 20:43:43
    (1)临时对象产生的条件: (1)创建一个无名对象时,会产生临时对象 如:int(8); int a = int(8); //这就是用一个临时对象初始化一个int对象 (2) 用构造函数作为隐式类型转换函数时,会创建临时对象。...
  • 19.临时对象什么时候产生? 隐式类型转换时,或函数返回对象时。 具体说就是,by value传递或是reference to const发生隐式类型转换。 20.消除临时对象之函数返回对象时 A fun(A &lhs,A& rhs){ return A(lhs...
  • 游离对象 临时对象 持久化对象

    千次阅读 2018-04-25 18:49:52
    临时对象是指new出的对象,没有对ID赋值;游离状态时候指对临时状态赋值ID的状态;持久化对象是指该对象已经插入数据库中;
  • C++临时对象

    2020-03-29 16:21:45
    //临时对象是看不见的,不会出现在程序代码中,会影响程序的执行效率,应避免产生临时对象 //临时对象产生的情况,(1):参数按值传递(2):返回值按值传递 class test{ public: test() :num(0){} test(int ...
  • c++ 临时对象

    2019-03-28 18:49:22
    临时对象 c++ 临时对象具有常量的属性,并且它的生命周期常常只存在于当前表达式中。 临时对象生命周期 struct A { ~A () { cout << "A" << endl; } }; A Fun() { return A(); } int ...
  • C++按值传递(产生临时对象) 按引用传递(不产生临时对象不占任何内存).rar
  • 神秘的临时对象

    2019-10-05 08:20:33
    直接调用构造函数将产生一个临时对象 临时对象的生命周期只有一条语句的时间 临时对象的作用域只在一条语句中 临时对象是c++中值得警惕的灰色地带 小结 直接调用构造函数将产生一个临时对象 临时对象时性能...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,376
精华内容 5,350
关键字:

临时对象