C++ 对象构造, 拷贝, 赋值和隐式类型转换总结

本文总结了C++中对象创建、拷贝构造、赋值、隐式类型转换等核心概念及其细节,重点关注效率与拷贝开销,并探讨了不同场景下的行为表现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C++ 中对象创建(构造)、拷贝、赋值、隐式类型转换的阶段性总结

关心效率和拷贝开销,写在代码注释中

关键字:对象创建、拷贝构造、赋值、隐式类型转换、explicit、按值传递 (passed by value)、按引用传递 (passed by reference)、参数传递、返回值传递

测试环境 VC 2010

目录


对象创建总结^

右边是左边的等价语义

  • 构造函数:ctor
  • 拷贝构造函数:copy ctor,是 ctor 的一种
  • 析构函数:dtor
  • 赋值操作函数:assign, operator=
  • 初始化对象:调用某个 ctor 创建对象
  • 初始化引用:给右值起一个别名
  • 初始化语义:初始化对象 或 引用,函数参数传递、返回值传递、捕获异常对象
  • 调用 copy ctor:初始化对象,按值传递 (passed by value) 时的 函数参数传递、返回值传递、捕获异常对象
  • 默认初始化:调用默认 ctor
  • 默认 ctor:可传 0 个参数的 ctor
  • 类型转换 ctor:可传 1 个参数的 ctor
  • 内部默认 ctor:C++ 内部产生的默认 ctor
  • 内部默认 copy ctor:C++ 内部产生的 copy ctor
  • 内部默认 assign:C++ 内部产生的 assign
  • 拷贝:调用 copy ctor 或 assign
  • 按成员拷贝:内部默认 copy ctor 和 assign 的行为
  • 拷贝的传递深度:拷贝在类的继承关系(基类、基类的基类)和成员关系(成员、成员的成员)间传递的深度

拷贝的传递^

C++ 内部默认的 copy ctor 和 assign 将 copy 传递到基类和成员,顺序如下:

  1. copy 先传递到基类,基类再传递到基类的基类,按继承格方向传递
  2. 等所有基类完成 copy 后,将 copy 传递到成员,然后成员类再按照 1、2 的顺序进行 copy 传递

总之,先做基类,后做成员的 copy 传递

传递到基类的拷贝^

设 Base 是 Derive 的基类,right 是 Derive 拷贝操作时的右值

内部默认 copy ctor 传递到基类 copy ctor 的语句:

Base(right): 因为基类 copy ctor 的参数是基类引用类型,所以 可接受子类对象 right

内部默认 assign 传递到基类 assign 的语句:

Base::operator=(right): 因为基类 assign 的参数是基类引用类型,所以可接受子类对象 right
(Base&) (*this) = right: 和上面等价
(*this) = (Base&) right: 语法错误

内部类型的默认初始化^

  • 静态存储(全局和名字空间的变量、类静态成员、局部静态变量),默认初始化为适当类型的 0

  • 局部存储

    以 double 为例:

    [cpp]  view plain copy
    1. double  v1;             // 未初始化,栈残留值,编译警告  
    2. double  v2();           // 语义错,这是函数声明  
    3. double  v3(0);          // 显式初始化为 0  
    4. double  v4 = double;    // 语法错,编译错误  
    5. double  v5 = double();  // 默认初始化为 0  
    6. double  v6 = double(0); // 显式初始化为 0  
  • 动态存储

    [cpp]  view plain copy
    1. double* v1 = new double;    // 未初始化,堆残留值  
    2. double* v2 = new double();  // 默认初始化为 0  
    3. double* v3 = new double(0); // 显式初始化为 0  

    内部类型 v1 和 v2 有差别,不同于 class/struct

内部类型初始化示例:

[cpp]  view plain copy
  1. // ctor  
  2. Complex(const Type& real = Type(), const Type& image = Type()) : m_real(real), m_image(image)  
  3. {}  
  4.   
  5. void user()  
  6. {  
  7.     Complex<double>     v1;  
  8.     Complex<double>*    v2 = new Complex<double>;  
  9.   
  10.     cout << v1 << _T("\n") << *v2 << _T("\n");  
  11. }  

输出:

[plain]  view plain copy
  1. (0, 0)  
  2. (0, 0)  

构造函数重载歧义^

程序编写缺陷,编译警告

[cpp]  view plain copy
  1. // ctor 1  
  2. Complex(const Type& real = Type(), const Type& image = Type()) : m_real(real), m_image(image)  
  3. {}  
  4. // ctor 2  
  5. Complex(const Type& real = Type()) : m_real(real), m_image(Type())  
  6. {}  
  7. // ctor 3  
  8. Complex() : m_real(Type()), m_image(Type())  
  9. {}  
  10.   
  11. void user()  
  12. {  
  13.     Complex<double>     v1;         // 编译错误,调用 ctor 1, 2, 3 中哪一个  
  14.     Complex<double>     v2(0);      // 编译错误,调用 ctor 1, 2 中哪一个  
  15.     Complex<double>     v3(0, 0);   // 无歧义,调用 ctor 1  
  16. }  

创建对象^

[cpp]  view plain copy
  1. Complex<double>     v1(1.2, 2.3);                   // 调用 ctor  
  2. Complex<double>     v1 = Complex<double>(1.2, 2.3); // 和上面等价,没有 copy  
  3. Complex<double>     v1(Complex<double>(1.2, 2.3));  // 和上面等价,没有 copy  

默认构造函数^

需要默认构造函数的地方:

  • 创建对象时,不写 () 和或 () 为空的初始化
  • 不在构造函数初始化列表中初始化的成员变量,用该成员的默认构造函数初始化
  • 不在构造函数初始化列表中初始化的基类,用基类的默认构造函数初始化

示例,考虑是否需要 UserEntry 的默认构造函数:

[cpp]  view plain copy
  1. vector<UserEntry>   user_vec;       // 不需要,1 个空的 vector  
  2. vector<UserEntry>   user_vec[100];  // 不需要,100 个 vector,每个 vector 都为空  
  3. vector<UserEntry>   user_vec(100);  // 需要,1 个元素个数为 100 的 vector,每个元素用 UserEntry 默认构造函数初始化  

类型转换构造函数^

外向内隐式类型转换

初始化^
[cpp]  view plain copy
  1. Complex<double>     v1 = 1.1;   // 隐式调用 ctor: Complex(1.1),没有 copy  
参数传递^
[cpp]  view plain copy
  1. void func(Complex<double> v);           // 前提:1. 参数为对象类型  
  2. void func(const Complex<double>& v);    //       2. 参数为 const 引用类型,但不能是非 const 引用类型  
  3.                                         //       3. 没有更匹配的重载,如 func(double v)  
  4.   
  5. func(1.1);                              // 隐式调用 ctor: Complex(1.1),没有调用 copy ctor  
返回值传递^
[cpp]  view plain copy
  1. Complex<double> func()          // 前提:返回类型为对象类型,而非引用类型  
  2. {  
  3.     return 1.1;                 // 隐式调用 ctor: Complex(1.1) 创建临时对象 [temp],没有调用 copy ctor  
  4. }  
  5. Complex<double> v1 = func();    // 临时对象 [temp] 被约束到变量名 v1,没有额外创建新对象  
  6.   
  7. Complex<double>& func()         // 不能返回非 const 引用类型  
  8. {  
  9.     return 1.1;                 // 编译错误 C2440: 无法将类型 double 转换为 Complex<double>&  
  10. }  
  11. const Complex<double>& func()   // 可以返回 const 引用类型,但不要返回局部变量  
  12. {  
  13.     return 1.1;                 // 编译警告 C4172: 返回一个局部或临时变量的地址  
  14. }  
多层隐式类型转换^

不要用多层隐式类型转换

[cpp]  view plain copy
  1. // 提供 double => Double 的转换  
  2. class Double  
  3. {  
  4. public:  
  5.     Double(double v = 0) : m_v(v)  
  6.     {}  
  7.   
  8.     double  m_v;  
  9. };  
  10.   
  11. // 提供 Double => DoubleDouble 的转换  
  12. class DoubleDouble  
  13. {  
  14. public:  
  15.     DoubleDouble(const Double& v = Double()) : m_v(v)  
  16.     {}  
  17.   
  18.     Double  m_v;  
  19. };  
  20.   
  21. // 提供 DoubleDouble => DoubleDoubleDouble 的转换  
  22. class DoubleDoubleDouble  
  23. {  
  24. public:  
  25.     DoubleDoubleDouble(const DoubleDouble& v = DoubleDouble()) : m_v(v)  
  26.     {}  
  27.   
  28.     DoubleDouble  m_v;  
  29. };  

《C++ 程序设计语言》中说不能进行多层隐式类型转换,但 VC 2010 测试结果如下:

变量初始化可进行最多 2 层隐式类型转换:

[cpp]  view plain copy
  1. DoubleDouble v1 = 1.1;       // double => Double(1.1) => DoubleDouble(Double(1.1))  
  2. DoubleDoubleDouble v2 = 1.1; // 试图 3 层隐式类型转换,编译错误 C2440: 无法将类型 double 转换为 DoubleDoubleDouble  
  3. DoubleDoubleDouble v3 = Double(1.1);    // Double(1.1) => DoubleDouble(Double(1.1)) => DoubleDoubleDouble(DoubleDouble(Double(1.1)))  

禁止函数参数传递进行多层次隐式类型转换,2 层也不行:

[cpp]  view plain copy
  1. void func(DoubleDouble v);  
  2. func(1.1);  // 编译错误 C2664: 函数无法将参数 double 转换为 DoubleDouble  

返回值按值传递可进行最多 2 层隐式类型转换:

[cpp]  view plain copy
  1. DoubleDouble func()  
  2. {  
  3.     return 1.1; // double => Double(1.1) => DoubleDouble(Double(1.1))  
  4. }  
  5. DoubleDoubleDouble func()  
  6. {  
  7.     return 1.1; // 试图 3 层隐式类型转换,编译错误 C2664  
  8. }  

explicit 类型转换构造函数^

禁止外向内隐式类型转换

[cpp]  view plain copy
  1. explicit  
  2. Complex(const Type& real = Type(), const Type& image = Type()) : m_real(real), m_image(image)  
  3. {}  

产生编译错误的情况:

  • 初始化隐式转换

    [cpp]  view plain copy
    1. Complex<double> v1 = 1.1;   // 编译错误 C2440  
  • 参数按值传递隐式转换

    [cpp]  view plain copy
    1. void func(Complex<double> v);  
    2. func(1.1);                  // 编译错误 C2664  
  • 返回值按值传递隐式转换

    [cpp]  view plain copy
    1. Complex<double> func()  
    2. {  
    3.     return 1.1;             // 编译错误 C2664  
    4. }  

没有编译错误的情况:

显式调用类型转换 ctor

[cpp]  view plain copy
  1. Complex<double> v1 = Complex<double>(1.1);  // 没有 copy  
  2.   
  3. func(Complex<double>(1.1));  
  4.   
  5. Complex<double> func()  
  6. {  
  7.     return Complex<double>(1.1);  
  8. }  

类型转换运算符^

参考《C++ 程序设计语言》11.4 转换运算符

  • 类型转换构造函数 ThisType(OtherType v),外向内转换:将其它类型转换为本类型,配合本类型的 operator@

  • 类型转换运算符 ThisType::operator OtherType(),内向外转换:将本类型转换为其它类型,配合其它类型的 operator@,其它类型可以是内部类型 int 及内部操作

这两种方法都能匹配 ThisType @ ThisType

但 应只使用一种,不要两种都用,会产生歧义:编译器无法判断使用本类型的 operator@,还是其它类型的 operator@

类型转换运算符示例:

[cpp]  view plain copy
  1. class Tiny  
  2. {  
  3. public:  
  4.     // 提供 int => Tiny 的转换  
  5.     Tiny(int v)  
  6.     {  
  7.         assgin(v);  
  8.     }  
  9.   
  10.     // 支持从 int 的 assgin  
  11.     Tiny& operator=(int v)  
  12.     {  
  13.         assgin(v);  
  14.         return *this;  
  15.     }  
  16.   
  17.     // 提供 Tiny => int 的转换  
  18.     operator int() const  
  19.     {  
  20.         return to_int();  
  21.     }  
  22.   
  23.     // 先写 to_int(),如果它使用的很频繁,再写 operator int() 转接到它  
  24.     int to_int() const  
  25.     {  
  26.         return m_data;  
  27.     }  
  28.   
  29. private:  
  30.     void assgin(int v)  
  31.     {  
  32.         if (v &~ 077)  
  33.             throw std::out_of_range("Tiny range must be 00 ~ 077");  
  34.         m_data = v;  
  35.     }  
  36.   
  37. private:  
  38.     char    m_data;  
  39. };  
  40.   
  41. // CAUTION:  
  42. // 不要同时使用两种类型转换和运算符重载方法  
  43. // VC 编译错误 C2666:有 2 个重载函数提供相似的类型转换,都能匹配 Tiny + Tiny:  
  44. // 1. int operator +(const Tiny &, const Tiny &)  
  45. // 2. C++ 内部的 operator+(int, int):因为有 Tiny => int 的转换运算符  
  46. #if 0  
  47. inline  
  48. int operator+(const Tiny& left, const Tiny& right)  
  49. {  
  50.     return left.to_int() + right.to_int();  
  51. }  
  52. #endif  
  53.   
  54. user()  
  55. {  
  56.     Tiny    v1 = 2;  
  57.     Tiny    v2 = 63;  
  58.     // Tiny  v3 = 64;       // 超出范围,抛出异常  
  59.   
  60.     int     i1 = v2 + 1;    // 创建 int i1 时不检查范围  
  61.   
  62.     // 下面是准确匹配,不会产生 Tiny(1) + Tiny(2),而是普通的内部 int + 操作  
  63.     // 重载优先级:准确匹配 > 标准转换 > 用户类型转换  
  64.     // 标准转换,如从 int => double 转换  
  65.     int     i2 = 1 + 2;  
  66.   
  67.     Tiny    v4 = v2 + 1;    // 创建 Tiny v4 时,调用其 ctor 检查范围,抛出异常  
  68.     v1 = v2 + 1;            // Tiny.assign(int(v2 + 1)) 检查范围,抛出异常  
  69. }  

拷贝构造函数^

拷贝构造函数定义^
[cpp]  view plain copy
  1. Complex(const Complex right)    // 错误的定义,引发无穷递归,因为 right 参数传递也是初始化语义,会调用 copy ctor 即自身  
  2. Complex(const Complex& right)   // 普通 copy ctor,不能改变右值  
  3. Complex(Complex& right)         // 用于破坏性 copy 的 copy ctor,可以改变右值  
拷贝初始化^
[cpp]  view plain copy
  1. Complex<double>     v1(1.2, 2.3);   // 调用 ctor  
  2. Complex<double>     v3(v1);         // 显式调用 copy ctor: v2 <= v1,仅一次 copy,没有 assign  
  3. Complex<double>     v2 = v1;        // 隐式调用 copy ctor,和上面等价  
参数传递^
[cpp]  view plain copy
  1. void func(Complex<double> v);   // 函数结束时销毁 v  
  2. func(v1);                       // 调用 copy ctor: v <= v1  
按值传递返回值^
  • 返回局部对象

    [cpp]  view plain copy
    1. Complex<double> func()  
    2. {  
    3.     Complex<double> v1(2.3, 1.2);   // 创建对象 v1  
    4.     return v1;                      // 调用 copy ctor 创建临时对象:[temp] <= v1  
    5. }                                   // 函数结束时销毁 v1  

    返回时构造局部对象,不调用 copy ctor 创建第 2 个临时对象,没有销毁局部变量的开销,效率较高

    [cpp]  view plain copy
    1. Complex<double> func_return_trans()  
    2. {  
    3.     return Complex<double>(2.3, 1.2);   // return 语句中的 Complex<double>(2.3, 1.2) 即是临时对象 [temp]  
    4. }  
  • 返回对象参数

    [cpp]  view plain copy
    1. Complex<double> func(Complex<double> v) // 参数传递调用 copy ctor 创建对象 v  
    2. {  
    3.     return v;                           // 调用 copy ctor 创建临时对象:[temp] <= v  
    4. }                                       // 函数结束时销毁 v  
  • 返回引用参数

    [cpp]  view plain copy
    1. Complex<double> func(Complex<double>& v)    // 参数传递没有创建对象  
    2. {  
    3.     return v;                               // 调用 copy ctor 创建临时对象:[temp] <= v  
    4. }  
  • 返回局部静态对象

    [cpp]  view plain copy
    1. Complex<double> func()  
    2. {  
    3.     static Complex<double> s_v;         // 第一次调用 func() 时,创建对象 s_v  
    4.     return s_v;                         // 调用 copy ctor 创建临时对象:[temp] <= s_v  
    5. }                                       // 函数结束时不销毁 s_v,程序结束时销毁 s_v  
  • 返回全局对象

    包括:

    • 名字空间中的对象
    • 使用 static 内部链接方式的全局和名字空间中的对象
    [cpp]  view plain copy
    1. // 程序初始化时创建对象 g_v,先于 main() 等用户入口函数  
    2. // 程序结束时销毁 g_v  
    3. Complex<double> g_v;  
    4.   
    5. Complex<double> func()  
    6. {  
    7.     return g_v;     // 调用 copy ctor 创建临时对象:[temp] <= g_v  
    8. }  
  • 返回动态对象

    有内存泄露

    [cpp]  view plain copy
    1. Complex<double> func()  
    2. {  
    3.     return  *(new Complex<double>(2.3, 1.2));   // 创建动态对象 [anonymous]  
    4.                                                 // 调用 copy ctor 创建临时对象:[temp] <= [anonymous]  
    5.                                                 // 内存泄露:动态对象 [anonymous] 无法访问  
    6. }  
  • 返回 auto_ptr 管理的动态对象

    [cpp]  view plain copy
    1. Complex<double> func()  
    2. {  
    3.     // 创建动态对象 [anonymous],并接受 auto_ptr 的管理  
    4.     // 调用 copy ctor 创建临时对象:[temp] <= [anonymous]  
    5.     return  *auto_ptr<Complex<double> >(new Complex<double>(2.3, 1.2));  
    6. }   // 函数结束时销毁 auto_ptr 管理的动态对象 [anonymous]  
函数调用表达式^

使用按值传递返回值的函数:

[cpp]  view plain copy
  1. func();                                         // 语句结束时销毁临时对象 [temp]  
  2. func().output(cout) << endl;                    // 语句结束时销毁临时对象 [temp]  
  3.   
  4. Complex<double> v1 = func();                    // 将临时对象 [temp] 约束到变量名 v1,没有新创建对象,没有 copy,没有 assign  
  5. Complex<double> v1(func());                     // 和上面等价  
  6.   
  7. Complex<double>& v1 = func();                   // 将临时对象 [temp] 约束到引用名 v1,没有新创建对象,没有 copy,没有 assign  
  8.   
  9. Complex<double> v1 = Complex<double>(func());   // 调用 copy ctor: v1 <= 临时对象 [temp],语句结束时销毁 [temp]  
  10.   
  11. Complex<double>& v1 = Complex<double>(func());  // 调用 copy ctor: 另一个临时对象 [temp 2] <= 临时对象 [temp]  
  12.                                                 // 将临时对象 [temp 2] 约束到引用名 v1  
  13.                                                 // 语句结束时销毁 [temp]  
按引用传递返回值^

返回引用的问题 参考《C++ 程序设计语言》7.3 返回值、11.6 大型对象

错误用法:

  • 返回局部变量

    [cpp]  view plain copy
    1. Complex<double>& func()  
    2. {  
    3.     Complex<double> v1(2.3, 1.2);  
    4.     return v1;                  // 编译警告 C4172: 返回一个局部或临时变量的地址  
    5. }  
  • 返回对象参数

    [cpp]  view plain copy
    1. Complex<double>& func(Complex<double> v)  
    2. {  
    3.     return v;                   // 编译警告 C4172  
    4. }  
  • 返回没有解除 auto_ptr 管理的动态对象

    [cpp]  view plain copy
    1. Complex<double>& func()  
    2. {  
    3.     Complex<double>* v1 = new Complex<double>(2.3, 1.2);  
    4.     auto_ptr<Complex<double> > sp_v1(v1);   // 动态对象 v1 接受 auto_ptr 的管理  
    5.     return *v1;                             // 返回动态对象销毁后的残留值,类似野指针  
    6. }                                           // 函数结束时销毁 auto_ptr 管理的动态对象 v1  
    7.   
    8. // 错误同上  
    9. Complex<double>& func()  
    10. {  
    11.     _s::auto_ptr<Complex<double> > sp_v1(new Complex<double>(2.3, 1.2));  
    12.     return *sp_v1.get();  
    13. }  

正确用法:

  • 返回静态对象

    有重入和线程安全性问题

    返回局部静态对象:

    [cpp]  view plain copy
    1. Complex<double>& func()  
    2. {  
    3.     static Complex<double> v1(2.3, 1.2);  
    4.     return v1;  
    5. }  

    返回全局对象:

    [cpp]  view plain copy
    1. Complex<double> g_Complex(2.3, 1.2);  
    2. Complex<double>& func()  
    3. {  
    4.     return g_Complex;  
    5. }  
  • 返回引用参数

    函数调用过程没有新创建对象,没有 copy

    但如果在使用函数调用表达式时,进行初始化、赋值,会发生 copy,而非约束到变量名

    [cpp]  view plain copy
    1. Complex<double>& func(Complex<double>& v)  
    2. {  
    3.     return v;  
    4. }  
    5.   
    6. Complex<double> v2 = func(v1);  // 调用 copy ctor: v1 <= func(),而非约束到变量名  
    7. func(v1).output(cout);          // 没有 copy  
  • 成员函数返回 *this

    this 是调用成员函数时的隐含参数,*this 等价于当前对象的引用

    适合接续形式的函数调用,如标准库中:

    [cpp]  view plain copy
    1. str_obj.append("first").append("second").append("third");   // 没有 str_obj 的 copy  
    2. str_obj += "first" += "second" += third;                    // 同上  
    3. cout << str_v << int_v << double_v;                         // 没有 cout 的 copy  
  • 返回动态对象

    需要用户负责释放

    [cpp]  view plain copy
    1. Complex<double>& func()  
    2. {  
    3.     Complex<double>* v1 = new Complex<double>(2.3, 1.2);  
    4.     return *v1;  
    5. }  
  • 返回解除 auto_ptr 管理的动态对象

    需要用户负责释放

    [cpp]  view plain copy
    1. Complex<double>& func()  
    2. {  
    3.     auto_ptr<Complex<double> > sp_v1(new Complex<double>(2.3, 1.2));  
    4.     return *sp_v1.release();    // 解除 auto_ptr 对动态对象的管理  
    5. }  

explicit 拷贝构造函数^

VC 编译错误:

C2558: 没有可用的 copy ctor 或 copy ctor 为 explicit
C2664: 不能将参数从类型 XXX 转换到 XXX ctor,因为 XXX 为 explicit

产生编译错误的情况:

  • 奇异情况

    由上面可知 VC 在这里并不进行 copy,但 copy ctor 声明 explicit 后却报错

    [cpp]  view plain copy
    1. Complex<double> v1 = Complex<double>(1.2, 2.3); // 编译错误 C2558  
  • 隐式调用 copy ctor

    [cpp]  view plain copy
    1. Complex<double> v1(1.2, 2.3);  
    2. Complex<double> v2 = v1;        // 编译错误 C2558  
  • 参数按值传递

    [cpp]  view plain copy
    1. void func(Complex<double> v);  
    2. func(v1);                       // 编译错误 C2664  
  • 返回值按值传递

    [cpp]  view plain copy
    1. Complex<double> func()  
    2. {  
    3.     Complex<double> v1(2.3, 1.2);  
    4.     return v1;                  // 编译错误 C2558  
    5. }  

没有编译错误的情况:

显式调用 copy ctor

[cpp]  view plain copy
  1. Complex<double> v1(Complex<double>(1.2, 2.3));  // 没有 copy  
  2.   
  3. Complex<double> v1(1.2, 2.3);  
  4. Complex<double> v2(v1);  

赋值^

尽量使用 copy ctor 即初始化,而不要用 assgin

copy ctor 只涉及一个步骤:从源对象创建对象

assgin 涉及两个步骤

  1. 释放现有对象的资源,动态存储、句柄、描述字等
  2. 从源对象重新建立对象的值,不是创建对象本体
赋值函数定义^
[cpp]  view plain copy
  1. Complex& operator=(const Complex& right)    // 普通 assign,不改变右值  
  2. Complex& operator=(Complex& right)          // 用于破坏性 copy 的 assign,可以改变右值  

赋值示例:

[cpp]  view plain copy
  1. Complex<double>       v1;       // 默认 ctor  
  2. v1 = Complex<double>(1.2, 2.3); // 创建临时对象 [temp]  
  3.                                 // assign: v1 <= [temp]  
  4.                                 // 语句结束时销毁临时对象 [temp]  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值