面试经验4-19

  1. 如何实现memcpy?

    如果从头实现memcpy,那么遇见src<dst的时候,并且有重叠的时候就嘎了。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    using LL = long long;
    
    const int N  = 1e5 + 5;
    
    const int INF = 2147483647;
    
    int a[N];
    int n;
    
    void my_memcpy(void* dst, const void* src, size_t size){
        if(dst==nullptr||src==nullptr)return;
        if(src+size>dst){
            char* lst_dst=(char *)dst+size-1;
            const char * lst_src=(char*)src+size-1;
    
            while(size--){
                *lst_dst--=*lst_src--;
            }
        }else{
            char* lst_dst=(char *)dst;
            const char * lst_src=(char*)src;
    
            while(size--){
                *lst_dst++=*lst_src++;
            }
        }
    }
    
    
    int main(){
        cin >> n;
        for(int i=0;i<n;++i){
            cin >> a[i];
        }
        my_memcpy(a+4, a, 5*sizeof(int));
        for(int i=0;i<n;++i){
            cout<<a[i]<<endl;
        }
        return 0;
    }
    
  2. c++ forward的作用。

    首先介绍一下什么是左值引用和什么是右值引用。左值引用就是一个持久性变量的引用(可以取地址)。右值引用是一个常量(临时值)的引用。左值引用只能绑定左值。右值引用只能绑定右值。右值引用不能绑定右值引用变量。因为变量是左值。

    再介绍一下完美转发:在函数模版中,将参数原封不动的转发给其他函数。包括参数的类型,值。

    比如下面的例子:

    #include <iostream>
    #include <utility>
    
    void func(int& x){
        std::cout<<"lvale: "<< x <<std::endl;
    }
    
    void func(int&& x){
        std::cout<<"rvale: "<< x <<std::endl;
    }
    
    template <typename T>
    void wrapper(T&& arg){
        func(std::forward<T>(arg));
    }
    
    int main(){
        int i=4;
        wrapper(i);
        wrapper(5);
        return 0;
    }
    

    使用了std::forward函数进行了完美转发。T&&表示可以接受某一类型的左值和右值。

  3. 介绍一下move函数:

    std::move是一个用于将左值强制转为右值引用的函数。转换了对象的类型,而没有改变对象的内容。节省了程序的时间和空间开销。参数是右值的时候,不需要复制。简而言之,move就是用来改变对象的状态或者所有权的。

    #include <iostream>
    #include <string>
    #include <vector>
    using namespace std;
    
    int main()
    {
        string str = "hello";
        cout << "before str: " << str << endl;
    
        vector<string> vstr;
        vstr.emplace_back(std::move(str));
        cout << "after  str: " << str << endl;
    
        return 0;
    }
    
    //result
    //before str: hello
    //after  str:
    
  4. c++中智能指针是一种管理动态内存的工具。进行自动的内存管理,避免手动分配和释放内存带来的错误。

    unique_ptr是资源管理的唯一对象。可以转移给其他unique_ptr,但是有所有权的unique_ptr析构的时候,被管理的对象将会被释放。

    shared_ptr允许多个shared_ptr共享同一个对象。在最后一个share_ptr离开他的作用域的时候,他便自动释放其管理的对象。shared_ptr用计数的方式追踪有多少个share_ptr对象指向同一个对象。创建一个share_ptr引用就加1,销毁就减1,引用计数为0的时候,shared_ptr就会删除管理的对象。这个计数器的实现原理是,每个share_ptr都会有一个指向counter的指针。

    weak_ptr用于于shared_ptr共享一个对象。不会增加引用计数,它不会阻止管理对象被删除。用lock成员函数从weak_ptr创建一个shared_ptr对象。这就可以访问被管理的对象,这样可以减少shared_ptr之间循环引用的问题。

    #include <iostream>
    #include <string>
    #include <vector>
    #include <memory>
    
    int main(){
        std::shared_ptr<int> p1=std::make_shared<int>(10);
        std::cout<<p1.use_count()<<std::endl;
    
        std::shared_ptr<int> p2=p1;
        std::cout<<p2.use_count()<<std::endl;
    
        std::weak_ptr<int> p3=p1;
        std::cout<<p3.use_count()<<std::endl;
    
        p1=nullptr;
        std::cout<<p1.use_count()<<std::endl;
        //p2.reset();
        std::cout<<p2.use_count()<<std::endl;
    
        return 0;
    }
    
    1. 主流电商用的多线程还是多进程

      多线程。多线程的优势是:

      a. 资源共享:共享内存空间,数据和变量。

      b. 上下文切换快速。线程切换代价更低,共享同一进程的地址空间和资源。

      c. 适合现代多核处理器。

    2. HTTP的头部里有什么内容:

      Host,被请求资源的主机名以及端口号。User-agent:制定客户端类型以及版本号。Referer:指定的源URL。Accept-language,接受的语言类型以及优先级。Cookie用来识别客户端身份。

    3. c++中管理内存的方式。

      手动管理,new和delete。智能指针:三种智能指针。RAII,资源获取即初始化。模版库。

    4. unique_ptr怎么赋值给另一个unique_ptr。

      用std::move;

    5. 多线程开发的问题:如何实现互斥和同步。c++11开始,支持语言级别的多线程。与平台无关。

      保护共享数据的问题:互斥量。

posted @ 2023-04-20 10:33  John_Ran  阅读(15)  评论(0编辑  收藏  举报