C++基础知识(3)

15、fork函数

fork函数会创建一个新的进程,这个新的进程跟调用fork()的进程一模一样,这两个进程都会继续运行。在子进程中,成功的fork(调用会返回0,在父进程中fork()返回子进程的pid。如果出现错误,fork()返回一个负值。fork出来的进程采用的是写时复制的方法,优化内存。

16、重载与覆盖

(1)重载

两个函数名相同,但是参数列表不同(个数、类型),返回值没有要求,在同一作用域中

(2)重写

子类继承父类,并且重新定义了父类的虚函数,这种情况就是重写

17、strcpy和strlen

strcpy是字符串拷贝函数:

char* strcpy(char* dest, const char* src);           

从src逐字节拷贝到dest,直到遇到‘\0’结束,因为没有指定长度,可能会导致拷贝越界,造成缓冲区溢出,其安全版本是strncpy()。

strlen函数是计算字符串长度的函数,返回从开始到‘\0’之间的字符个数。

18、++i与i++的区别

++i先自增再返回,而i++是先返回再自增。

// ++i的实现
int& int::operator++()
{
    *this += 1;
    return *this;
}
// i++的实现
const int int::operator(int)
{
    int oldValue = *this;
    ++(*this);
    return oldValue;
}

19、智能指针shared_ptr是如何实现的

#ifndef SMART_PTR_H
#define SMART_PTR_H

template<typename T>
class SmartPtr
{
private:
    T* ptr; // 底层真实的指针
    int* use_count; // 保存当前对象被多少指针引用计数

public:
    // 有参构造
    SmartPtr(T* p); // SmartPtr<int>p(new int(2))
    // 拷贝构造
    SmartPtr(const SmartPtr<T>&orig);//SmartPtr<int>q(p)

    SmartPtr<T>&operator=(const SmartPtr<T>&rhs);//q=p
    ~SmartPtr();
    T operator*(); //重载*解引用
    T* operator->(); // 重载->取成员操作
    T* operator+(int i);// 重载+指针加常数
    int operator-(SmartPtr<T>&t1);// 重载-实现两个智能指针相减
    int getcount(); // 获取当前对象被多少指针引用
};

template<typename T>
SmartPtr<T>::SmartPtr(T* p)
{
    ptr = p;
    try{
        use_count = new int(1);
    }catch(...)
    {
        delete ptr;
        ptr = nullptr;
        delete use_count;
        use_count = nullptr;
    }
}

template<typename T>
SmartPtr<T>::SmartPtr(const SmartPtr<T>&orig)
{
    use_count = orig.use_count;
    this->ptr = orig.ptr;
    ++(*use_count);
}

template<typename T>
SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<T>&rhs)
{
    ++*(rhs.use_count);
    if((--*(use_count))==0)
    {
        delete ptr;
        ptr = nullptr;
        delete use_count;
        use_count = nullptr;
    }
    ptr = rhs.ptr;
    use_count = rhs.use_count;
    return *this;
}

template<typename T>
SmartPtr<T>::~SmartPtr()
{
    if(--(*use_count)==0)
    {
        delete ptr;
        ptr = nullptr;
        delete use_count;
        use_count = nullptr;
    }
}

template<typename T>
T SmartPtr<T>::operator*()
{
    return *ptr;
}

template<typename T>
T* SmartPtr<T>::operator->()
{
    return ptr;
}

template<typename T>
T* SmartPtr<T>::operator+(int i)
{
    return ptr + i;
}

template<typename T>
int SmartPtr<T>::operator-(SmartPtr<T>&t1)
{
    return this->ptr - t1.ptr;
}

template<typename T>
int SmartPtr<T>::getcount()
{
    return *use_count;
}

#endif

20、C++是怎么定义常量的?常量通常放在哪个位置?

常量在C++里的定义就是一个顶层的const对象类型,常量定义必须初始化。局部常量存放在栈区;全局常量,编译器一般不分配内存,而是存放在符号表中,提高效率;字面值常量比如字符串,放在常量区。

(符号表是一张抽象的表格,将信息在里面,可以按指定的键来搜索这些信息,而且键不能重复。)

21、顶层const和底层const

首先需要明确的是const是一个限定符,被它修饰的变量是不能改变的,所以对于一般的类型其实没有顶层与底层const之分,只有指针这种复合类型的基本变量才有区别。

(1)顶层const

顶层const是常量指针,const是用来修饰指针本身的,可以简单把顶层理解为表面看到的层次,指针表面看起来就是指针,所以当const加在指针前面就是顶层const

(2)底层const

底层const是指向常量的指针,const修饰的是指针指向的对象,可以把底层简单理解为内在深层次的东西,那么指针指向的对象就是内在的,所以当const修饰指针指向的对象时,那么它就是底层的const

int nums1 = 4;
int nums2 = 5;

int* const p1 = &nums1; // 顶层const
int const *q1 = &nums1; // 底层const
const int* q2 = &nums1; // 底层const

*p1 = nums2;    // 正确,指针是常量不可以修改,但是,指针指向的对象可以修改
// *q1 = nums2; // 报错,不能通过指针修改对象,因为底层const修饰的是指针指向的对象

int* temp = p1; // 正确,虽然p1是常量指针,但是只是作为赋值,并没有修改指针
// p1 = &nums2; // 错误,p1是常量指针,不能被修改

const int* const ptr = &nums1; // 既有顶层const,也有底层const
// *ptr = nums2; // 错误
// ptr = &nums2; // 错误
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

czy1219

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值