C++临时对象销毁时间

下面这段代码会输出什么?

[cpp] view plaincopy

  1. const char* p = string("hello temprary string").c_str();
  2. cout << p;

下面这段代码运行之后会怎样?

[cpp] view plaincopy

  1. #include <vector>
  2. class Foo
  3. {
  4. public:
  5. Foo()
  6. {
  7. _p = new char[32];
  8. }
  9. ~Foo()
  10. {
  11. delete _p;
  12. }
  13. private:
  14. char* _p;
  15. };
  16. int main()
  17. {
  18. std::vector<Foo> cont;
  19. cont.push_back(Foo());
  20. return 0;
  21. }

第一个会输出奇怪的字符串,第二个会崩溃。

Why?这是临时对象提前销毁造成的。

临时对象会在什么情况下被创建,msdn上介绍有以下几种情况:

  • To initialize a const reference with an initializer of a type different from that of the underlying type of the reference being initialized.
  • To store the return value of a function that returns a user-defined type. These temporaries are created only if your program does not copy the return value to an object. For example:
    UDT Func1();    //  Declare a function that returns a user-defined
                    //   type.
    
    ...
    
    Func1();        //  Call Func1, but discard return value.
                    //  A temporary object is created to store the return
                    //   value.
    

    Because the return value is not copied to another object, a temporary object is created. A more common case where temporaries are created is during the evaluation of an expression where overloaded operator functions must be called. These overloaded operator functions return a user-defined type that often is not copied to another object.

    Consider the expression ComplexResult = Complex1 + Complex2 + Complex3. The expression Complex1 + Complex2 is evaluated, and the result is stored in a temporary object. Next, the expression temporary + Complex3 is evaluated, and the result is copied to ComplexResult(assuming the assignment operator is not overloaded).

  • To store the result of a cast to a user-defined type. When an object of a given type is explicitly converted to a user-defined type, that new object is constructed as a temporary object.

临时对象何时被销毁呢,还是看msdn的介绍:

Temporary objects have a lifetime that is defined by their point of creation and the point at which they are destroyed. Any expression that creates more than one temporary object eventually destroys them in the reverse order in which they were created. The points at which destruction occurs are shown in the following table.

Destruction Points for Temporary Objects


Reason Temporary Created


Destruction Point


Result of expression evaluation


All temporaries created as a result of expression evaluation are destroyed at the end of the expression statement (that is, at the semicolon), or at the end of the controlling expressions for for, if, while, do, and switch statements.


Initializingconstreferences


If an initializer is not an l-value of the same type as the reference being initialized, a temporary of the underlying object type is created and initialized with the initialization expression. This temporary object is destroyed immediately after the reference object to which it is bound is destroyed.

注意第一条:由于表达式的计算产生的临时对象会在表达式计算完成(遇到;号)之后被销毁。

所以:

第一个问题中,p在第一行代码之后指向了一被销毁的内存。

第二个问题中,Foo在push_back的那行代码之后被销毁,_p被delete。而vector析构的时候会析构每个元素,_p又被delete,崩溃!

编译器默认的operator=只是赋值每一个字段。要解决第二个问题,可以在operator=中对_p申请另外的内存再拷贝。

关于临时对象的析构造成的问题还可以举出很多例子。掌握了它析构的时机才能很好的避免类似错误。

http://blog.csdn.net/passion_wu128/article/details/38959465

时间: 2024-10-25 18:56:27

C++临时对象销毁时间的相关文章

C++返回对象的问题(临时对象问题)

结论: (1)如果一个类的方法返回一个对象(某个类对象),在使用中均应该将此对象首先赋值给一个局部变量,之后再使用此局部变量.决不能以此临时变量为中间变量再调用其它的. 1,有关 QString::toStdString() 使用的一个细节问题 例子: // 1 ,错误的,cStr的值为非法 QString str = "Hello, world!"; char *cStr = str.toStdString().c_str(); // 2,正确的用法 std::string sstr

c# -- 对象销毁和垃圾回收

有些对象需要显示地销毁代码来释放资源,比如打开的文件资源,锁,操作系统句柄和非托管对象.在.NET中,这就是所谓的对象销毁,它通过IDisposal接口来实现.不再使用的对象所占用的内存管理,必须在某个时候回收:这个被称为无用单元收集的功能由CLR执行. 对象销毁和垃圾回收的区别在于:对象销毁通常是明确的策动:而垃圾回收完全是自动地.换句话说,程序员负责释放文件句柄,锁,以及操作系统资源:而CLR负责释放内存. 本章将讨论对象销毁和垃圾回收,还描述了C#处理销毁的一个备选方案--Finalize

第23课.神秘的临时对象

1.下面程序输出什么?为什么? #include <stdio.h> class Test { int mi; public: Test(int i) { mi = i; } Test() { Test(0); //直接调用了构造函数,会产生一个临时对象:Test(0)这个构造函数对这个临时对象进行初始化后.就被析构函数销毁了.所以对这个程序而言.这句话没有任何意义.才导致了,打印的随机值. } void print() { printf("mi = %d\n", mi);

转:C++中临时对象及返回值优化

http://www.cnblogs.com/xkfz007/articles/2506022.html 什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行时确实生成了这样的对象. 通常出现在以下两种情况: (1)为了使函数调用成功而进行隐式类型转换的时候. 传递某对象给一个函数,而其类型与函数的形参类型不同时,如果可以通过隐式转化的话可以使函数调用成功,那么此时会通过构造函数生成一个临时对象,当函数返回时临时对象即自动销毁.如下例: //计算字符ch

C++11系列之——临时对象分析

/*C++中返回一个对象时的实现及传说中的右值——临时对象*/ 如下代码: 1 /**********************************************/ 2 class CStudent; 3 CStudent GetStudent() 4 { 5 CStudent loc_stu; 6 return loc_stu; 7 } 8 9 int main() 10 { 11 CStudent stu = GetStudent(); 12 } 13 /************

[转] C++中临时对象及返回值优化

http://www.cnblogs.com/xkfz007/articles/2506022.html 什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行时确实生成了这样的对象. 通常出现在以下两种情况: (1)为了使函数调用成功而进行隐式类型转换的时候. 传递某对象给一个函数,而其类型与函数的形参类型不同时,如果可以通过隐式转化的话可以使函数调用成功,那么此时会通过构造函数生成一个临时对象,当函数返回时临时对象即自动销毁.如下例: //计算字符ch

c++ 临时对象

我们知道在C++的创建对象是一个费时,费空间的一个操作.有些固然是必不可少,但还有一些对象却在我们不知道的情况下被创建了.通常以下三种情况会产生临时对象: 1,以值的方式给函数传参: 2,类型转换: 3,函数需要返回一个对象时: 现在我们依次看这三种情况: 一,以值的方式给函数传参. 我们知道给函数传参有两种方式.1,按值传递:2,按引用传递.按值传递时,首先将需要传给函数的参数,调用拷贝构造函数创建一个副本,所有在函数里的操作都是针对这个副本的,也正是因为这个原因,在函数体里对该副本进行任何操

临时对象与NRV技术

<More Effective C++>中讲到,在C++中真正的临时对象是看不见的,它们不出现在你的源代码中.建立一个没有命名的非堆(non-heap)对象会产生临时对象,这种未命名的对象通常在两种条件下产生:为了使函数成功调用而进行隐式类型转换和函数返回对象时. 1 size_t countChar(const string& str, char ch); 2 3 int main() 4 { 5 char c; 6 cin >> c >> setw(MAX_

More Effective C++----(19)理解临时对象的来源

Item M19:理解临时对象的来源 当程序员之间进行交谈时,他们经常把仅仅需要一小段时间的变量称为临时变量.例如在下面这段swap(交换)例程里: template<class T> void swap(T& object1, T& object2) { T temp = object1; object1 = object2; object2 = temp; } 通常把temp叫做临时变量.不过就C++而言,temp根本不是临时变量,它只是一个函数的局部对象.(一切事物皆对象