C++基础相关杂烩

1. 拷贝构造函数

    1.1. 拷贝构造函数的作用是通过一个对象生成另外一个对象,或者是对象作为函数参数或者函数返回值进行值传递时。

    1.2. 拷贝分为深拷贝(值拷贝)和浅拷贝(位拷贝):

    当类成员含有资源(指针)时,其中深拷贝(值拷贝)是将类成员资源复制一份,因此指针指向的是不同的地址,而浅拷贝(位拷贝)只是指针地址的拷贝,因此指针指向相同的地址。

    1.3. 浅拷贝与深拷贝的经典写法(参考string类源码):

        假设定义一个class MyString,类定义如下:

#ifndef _MY_STRING
#define _MY_STRING

#include <iostream>

using namespace std;

class MyString
{
public:
    MyString() : m_head(NULL), m_len(0) {}
    MyString(char* s);
    const MyString& operator= (const MyString& s);

public:
    char* m_head;
    size_t m_len;
};

#endif // __MY_STRING
        深拷贝函数的写法如下:

const MyString& MyString::operator= (const MyString& s)
{
    if(this != &s)
    {
        m_len = s.m_len;
        m_head = new char[strlen(s.m_head)+1];
        strcpy(m_head, s.m_head);
    }

    return *this;
}
        浅拷贝函数的写法如下:

const MyString& MyString::operator= (const MyString& s)
{
    if(this != &s)
        m_head = s.m_head;

    return *this;
}

    1.4.   如果没有自己定义拷贝构造函数,C++编译器自动分配的是浅拷贝(位拷贝)。

    当类成员含有指针变量时,需要记得自己定义拷贝构造函数,因为如果使用默认的浅拷贝,会造成问题如下:

    (1)当销毁两个对象时,指针成员变量指向的同一段内存被释放两次;

    (2)当通过其中的一个对象的指针改变其所指向对象的内容时,另外一个对象的指针成员所指向的内容也跟着发生了变化。

    为了避免上述问题,除了自己定义深拷贝的拷贝构造函数外,还可以用写时拷贝(copy on write)来解决浅拷贝带来的问题。



        


2. const的作用:

    2.1. const与变量:

        (1)const修饰变量,则该变量是常量。

        (2)const修饰指针,如果const在*左边,表示指针所指向的对象是一个常量,不可修改,例如const int* a或者是int const *a;如果const在*右边,表示 指针是一个常量指针,所指向的地址不可修改,例如int* const a。

    2.2. const与函数:

        2.2.1. 修饰函数输入参数时,保证函数内部无法修改该参数。

        2.2.2. 修饰函数返回值时:

            (1)如果返回值是对象或值,没有任何意义。

            (2)如果返回值是指针,则返回值指针指向的内容是常量,不可被修改。

            (3)返回值是引用,用const修饰引用并返回可以比返回对象提高效率,因为无需进行对象传递,对象传递过程中涉及到对象的拷贝和销毁,但是需要注意的是如果返回的是对象的引用,一定要加const修饰,表示只读,来避免修改掉所读变量的危险,引起数据错误。

    2.3. const与类:

        2.3.1. const修饰成员函数放在成员函数最后,表示该函数不能修改类的属性。




3. C++重载,重写和隐藏的概念:

    3.1. 需要特别注意的点:

        由于C++具有隐藏的特点,所以某个类定义了带参数的构造函数,而没有定义无参数的构造函数,则初始化一个对象时,无法调用其无参数的构造函数,因为带参数的构造函数已经将基类(可能不是用户定义的而是系统定义的)的不带参数的构造函数隐藏了。             




4. i++和++i的区别:

    i++先把i值拿来执行所在的语句,执行完再+1;++i先将i+1,然后再拿来执行所在的语句。




5. C++用throw抛出异常。




6. 宏:

    6.1. 宏的作用:

        (1)批量替换程序中的常量;

        (2)减少函数调用的开销。

    6,.2. 宏定义需要注意的地方:

        (1)宏定义中的空格不容忽视;

        (2)把宏定义中每个变量和表达式都用括号括起来;

        (3)类型定义最好不用宏而应该用typedef,因为涉及到指针类型的时候有可能会出现问题,例如:

                #define int* INTPTR;

                INTPTR ptr1, ptr2    ==>   int* ptr1 && int ptr2




7. 类析构函数的调用:

    如果是new生成的对象,则在delete指向该对象的指针时调用析构函数;

    如果是静态声明一个对象,例如class Test声明一个对象Test test,则在此对象出作用域的时候自动调用类的析构函数。




8. raii用法:

   8.1. 字面解释:

        资源获取即初始化

    8.2. 作用:

        避免当因为某些异常情况退出时,没有及时释放程序中的资源。

    8.3. 实现方法:

        将资源获取,使用和释放封装成类,当由于异常情况退出时,由于静态声明的对象在出作用域时会自动调用类的析构函数,所以可以在析构函数中保证资源的释放。

    8.4. 注意事项:

        这种类不允许在堆上创建对象,也不允许复制和赋值操作,所以一般定义一个基类,使派生类私有继承基类来保证这些注意事项,然后在派生类中覆盖类的构造函数,析构函数,实现操作资源的函数。




9. 应避免垂悬指针和野指针:

    9.1. 垂悬指针指的是指向已经被释放的资源,应当重新将其指向NULL,尤其要注意函数中的局部变量存在于堆栈中,函数调用结束时这些变量会销毁,指向这些变量的指针如果从返回值中返回就变成了垂悬指针。

    9.2. 野指针指的是未进行初始化的指针。

    9.3. static指针未进行显示初始化的时候会被初始化为0。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值