• 类和动态内存分配


    类和动态内存分配

    整理自《C++ Primer Plus》

    1. 动态内存和类

    • 静态类成员有一个特点:无论创建了多少对象,程序都只创建一个静态类变量副本。也就是说,类的所有对象共享同一个静态成员。静态数据成员在类声明中声明,在包含类方法的文件中初始化。

    • 复制构造函数用于将一个对象复制到新创建的对象中。也就是说,也就是说,它用于初始化过程中(包括按值传递参数),而不是常规的赋值过程中。按值传递意味着创建原始变量的一个副本。由于按值传递对象将调用复制构造函数,因此应该按引用传递对象。这样可以节省调用构造函数的时间以及存储新对象的空间。
      默认的复制构造函数逐个复制非静态成员(成员复制也被称为浅复制),复制的是成员的值。
      深度复制。必须定义复制构造函数的原因在于,一些类成员是使用new初始化的、指向数据的指针,而不是数据本身。

    2. 在构造函数中使用new时应注意的事项

    • 如果在构造函数中使用new来初始化对象的指针成员时,则应在析构函数中使用delete。
    • new 和delete 必须相互兼容。new对应于delete, new[] 对应于delete[]。
    • 如果有多个构造函数,则必须以相同的方式使用new,要么都带中括号,要么都不带。
    • 应定义一个复制构造函数,通过深度复制将一个对象初始化为另一个对象。
    • 应当定义一个赋值运算符,通过深度复制将一个对象复制给另一个对象。该方法完成这些操作:检查自我赋值的情况,释放成员指针以前指向的内存,复制数据而不仅仅是数据的地址,并返回一个指向调用对象的引用。

    3. 有关返回对象的说明

    • 返回指向const对象的引用
      使用const引用的常见原因是旨在提高效率,但对于何时可以采用这种方式存在一些限制。如果函数返回(通过调用对象的方法或将对象作为参数)传递给它的对象,可以通过返回引用来提高其效率。
    Vector force1(50, 60);
    Vector force2(10, 70);
    Vector max;
    max = Max(force1, force2);
    
    // version1
    Vector Max(const Vector & v1, const Vector & v2)
    {
    	if (v1.magval() > v2.magval())
    		return v1;
    	else
    	{
    		return v2;
    	}
    }
    
    // version2
    
    const Vector & Max(const Vector & v1, const Vector & v2)
    {
    	if (v1.magval() > v2.magval())
    		return v1;
    	else
    	{
    		return v2;
    	}
    }
    

    说明:首先,返回对象将调用复制构造函数,而返回引用不会。因此,第二个版本所作的工作更少,效率更高。其次,引用指向的对象应该在调用函数执行时存在。第三,v1和v2都被声明为const引用,因此返回类型必须为const,这样才匹配。

    • 返回指向非const对象的引用。
      两种常见的返回非const对象情形是,重载赋值运算符以及重载与cout一起使用的<<运算符。

    • 返回对象
      如果被返回的对象是被调用函数中的局部变量,则不应按引用方式返回它,因为在被调用函数执行完毕时,局部对象将调用其析构函数。因此,当控制权回到调用函数时,引用指向的对象将不再存在。在这种情况下,应返回对象而不是引用。通常,被重载的算术运算符属于这一类。

    • 返回const对象
      总之,如果方法或函数要返回局部对象,则应返回对象,而不是指向对象的引用。在这种情况下,将使用复制构造函数来生成返回的对象。如果方法或函数要返回一个没有公有复制构造函数的类的对象,它必须返回一个指向这种对象的引用。最后,有些方法和函数(如重载的赋值运算符)可以返回对象,也可以返回指向对象的引用,在这种情况下,应首选引用,因为其效率更高。

    • 在下述情况下析构函数将被调用
      如果对象是动态变量,则当执行完定义该对象的程序块时,将调用该对象的析构函数。
      如果对象是静态变量(外部、静态、静态外部或来自名称空间),则在程序结束时调用对象的析构函数。
      如果对象是用new创建的,则仅当您显示使用delete删除对象时,其析构函数才会被调用。

    • 类方法
      对于const数据成员,必须在执行到构造函数体之前,即创建对象时进行初始化。C++提供了一种特殊的语法来完成上述工作,它叫做初始化成员列表。
      成员初始化列表由逗号分隔的初始化列表组成(前面带冒号)。它位于参数列表的右括号之后、函数体左括号之前。如果数据成员的名称为mdata,并需要将它初始化为val,则初始化器为mdata(val)。只有构造函数可以使用这种初始化列表语法。不能将成员初始化列表语法用于构造函数之外的其他类方法。

  • 相关阅读:
    Codeforces训练记录
    2017中国大学生程序设计竞赛-杭州站
    Codeforces Round #636 (Div. 3)
    自适应Simpson积分
    2020牛客暑期多校训练营(第九场)- E. Groundhog Chasing Death
    2020 Multi-University Training Contest 6
    拉格朗日插值法学习笔记
    二次剩余学习笔记
    2020 Multi-University Training Contest 3
    2020 Multi-University Training Contest 2
  • 原文地址:https://www.cnblogs.com/adtxl/p/11494574.html
Copyright © 2020-2023  润新知