日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

大-杂-烩

發(fā)布時(shí)間:2023/12/18 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 大-杂-烩 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

計(jì)算機(jī)網(wǎng)絡(luò)

  • 在利用網(wǎng)絡(luò)socket進(jìn)行通信時(shí),選擇tcp協(xié)議進(jìn)行交互,利用send函數(shù)進(jìn)行數(shù)據(jù)發(fā)送,我們都知道send函數(shù)的返回結(jié)果為0時(shí)代表對端關(guān)閉了連接,那么如果發(fā)送0字節(jié)數(shù)據(jù)時(shí)是不是也會返回0?這樣會不會有歧義呢?
    答:調(diào)用send函數(shù)發(fā)送0字節(jié)數(shù)據(jù)時(shí),send(,0,) 第三個(gè)參數(shù)代表發(fā)送的字節(jié)數(shù),本端的操作系統(tǒng)的協(xié)議棧并不會把數(shù)據(jù)發(fā)送出去(這里可以通過tcpdump截包佐證只有tcp建鏈的包,后續(xù)沒有任何數(shù)據(jù)包),但是返回的結(jié)果依然是0,所以這里確實(shí)是會有一點(diǎn)歧義。對于接收端而言,并不會有任何響應(yīng),另外如果是阻塞式的socket,那么接收端的緩沖區(qū)并沒有數(shù)據(jù)收到,所以程序會阻塞在recv處(可以通過gdb運(yùn)行程序查看)。另外發(fā)送0字節(jié)的數(shù)據(jù)是沒有任何意義的,所以盡量避免。

    //TODO 包亂序 丟包重傳怎么解決? 粘包是什么,怎么解決?(固定包長度,固定結(jié)束符,包頭包體結(jié)構(gòu))
  • 2.陳碩關(guān)于網(wǎng)絡(luò)編程時(shí)提出的幾個(gè)問題

    程序在本機(jī)測試正常,放到網(wǎng)絡(luò)運(yùn)行上就經(jīng)常出現(xiàn)數(shù)據(jù)收不全的情況?
    TCP 協(xié)議真的有所謂的“粘包問題”嗎?該如何設(shè)計(jì)打包拆包的協(xié)議?又該如何編碼實(shí)現(xiàn)才不會掉到陷阱里?
    帶外數(shù)據(jù)(OOB)、信號驅(qū)動IO這些高級特性到底有沒有用?
    網(wǎng)絡(luò)協(xié)議格式該怎么設(shè)計(jì)?發(fā)送 C struct 會有對齊方面的問題嗎?對方不用 C/C++ 怎么通信? 將來服務(wù)端軟件升級,需要在協(xié)議中增加一個(gè)字段,現(xiàn)有的客戶端就必須強(qiáng)制升級?
    要處理幾千上萬的并發(fā)連接,似乎書上講的傳統(tǒng) fork() 模型應(yīng)付不過來,該用哪種并發(fā)模型呢? 試試 select、poll、epoll 這種 IO 復(fù)用模型吧,又感覺非阻塞IO陷阱重重,怎么程序的 CPU 使用率一直是100%?
    要不改用現(xiàn)成的 libevent 網(wǎng)絡(luò)庫吧,怎么查詢一下數(shù)據(jù)庫就把其他連接上的請求給耽誤了?
    再用個(gè)線程池吧。萬一發(fā)回響應(yīng)的時(shí)候?qū)Ψ揭呀?jīng)斷開連接了怎么辦?會不會串話?
    讀過《UNIX 環(huán)境高級編程》,想用多線程來發(fā)揮多核 CPU 的效率, 但對程序該用哪種多線程模型感到一頭霧水? 有沒有值得推薦的適用面廣的多線程 IO 模型? 互斥器、條件變量、讀寫鎖、信號量這些底層同步原語哪些該用哪些不該用? 有沒有更高級的同步設(shè)施能簡化開發(fā)? 《UNIX 網(wǎng)絡(luò)編程(第二卷)》介紹的那些琳瑯滿目的IPC機(jī)制到底用哪個(gè)才能兼顧開發(fā)效率與可伸縮性?
    網(wǎng)絡(luò)編程和多線程編程的基礎(chǔ)打得差不多,開始實(shí)際做項(xiàng)目了,更多問題撲面而來:
    網(wǎng)上聽人說服務(wù)端開發(fā)要做到 7x24 運(yùn)行,為了防止內(nèi)存碎片連動態(tài)內(nèi)存分配都不能用, 那豈不是連 C++ STL 也一并禁用了?硬件的可靠性高到值得去這么做嗎?
    傳聞服務(wù)端開發(fā)主要通過日志來查錯(cuò),那么日志里該寫些什么?日志是寫給誰看的?怎樣寫日志才不會影響性能?
    分布式系統(tǒng)跟單機(jī)多進(jìn)程到底有什么本質(zhì)區(qū)別?心跳協(xié)議為什么是必須的,該如何實(shí)現(xiàn)?
    C++ 的大型工程該如何管理?庫的接口如何設(shè)計(jì)才能保證升級的時(shí)候不破壞二進(jìn)制兼容性?
    這本《Linux 多線程服務(wù)端編程》中,作者憑借多年的工程實(shí)踐經(jīng)驗(yàn)試圖解答以上疑問。當(dāng)然,內(nèi)容還遠(yuǎn)不止這些……
    —摘自陳碩博客

    操作系統(tǒng)

    數(shù)據(jù)結(jié)構(gòu)

    GDB調(diào)試

    1.編譯時(shí)增加編譯選項(xiàng) -fstack -protector 可以在檢測到緩沖區(qū)溢出時(shí),立刻終止正在執(zhí)行的程序,并提示其檢測到緩沖區(qū)存在的溢出問題。

    C++語法

    1.多繼承時(shí),子類的構(gòu)造函數(shù)應(yīng)該怎么寫?
    如果父類里面有顯示的聲明構(gòu)造函數(shù),一般來說子類不需要再顯示的聲明構(gòu)造函數(shù),會生成一個(gè)默認(rèn)構(gòu)造函數(shù)。當(dāng)多繼承時(shí)可能會存在多義性,其實(shí)也很好理解,比如C繼承自類A和類B,而類A和類B都有相同的構(gòu)造函數(shù)(參數(shù)列表一樣),那么這個(gè)時(shí)候如果不在類C里面顯示的聲明一個(gè)新的構(gòu)造函數(shù),則編譯器會提示“C::C”不明確,即系統(tǒng)不知道去默認(rèn)調(diào)用A還是B的構(gòu)造函數(shù)。
    2.類中的靜態(tài)成員到底是什么屬性?
    常常會見到,類里面有一些靜態(tài)成員的聲明,其實(shí)static作用在類里面,說明這個(gè)成員是屬于類的,使用時(shí),需要加域名空間才能使用。與不在類中的static類似,比如在.cpp中定義一個(gè)static的成員,不管是靜態(tài)變量,還是靜態(tài)函數(shù),都只能在本cpp里面可見。有一點(diǎn)區(qū)別是,類中的靜態(tài)成員,在使用之前需要使用 如下方法初始化

    class A {static int status; } A::status = 1; //可以與類的定義在不同的文件

    3.派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)的調(diào)用順序

    class A { //構(gòu)造和析構(gòu)在此省略 } class B { //構(gòu)造和析構(gòu)在此省略 } class C:public A,public B { //子類的構(gòu)造和析構(gòu) }

    利用斷點(diǎn)調(diào)式逐步執(zhí)行就能發(fā)現(xiàn)執(zhí)行順序是
    A的構(gòu)造函數(shù)執(zhí)行
    B的構(gòu)造函數(shù)執(zhí)行
    C的構(gòu)造函數(shù)執(zhí)行
    C的析構(gòu)函數(shù)執(zhí)行
    B的析構(gòu)函數(shù)執(zhí)行
    A的析構(gòu)函數(shù)執(zhí)行
    規(guī)律是,無論繼承是什么順序,衍生類的構(gòu)造函數(shù)都是最后執(zhí)行,A和B的構(gòu)造函數(shù)是誰繼承在前誰先執(zhí)行
    4.多態(tài)(類型轉(zhuǎn)換)
    基類的指針可以指向派生類的對象,編譯器會隱式的執(zhí)行這種派生類到基類的轉(zhuǎn)換。之所以能轉(zhuǎn)換是因?yàn)槊恳粋€(gè)派生類都包含一個(gè)基類的全部。
    5.虛繼承
    考慮一種情況,基類A被A1和A2同時(shí)繼承,B繼承了A1和A2,此時(shí)A就會同時(shí)被繼承兩次(這樣說可能不妥),所以在訪問變量時(shí),可能會存在一些二意性,而且兩個(gè)基類也比較占空間。這時(shí)候就需要虛基類的出現(xiàn)了。虛基類無論被何種方式繼承,都只會被初始化一次,且基類的初始化需要孫子類或者更下級的類來完成初始化。

    6.類型轉(zhuǎn)換構(gòu)造函數(shù)
    簡單點(diǎn)來說,類型轉(zhuǎn)換構(gòu)造函數(shù)就是帶有一個(gè)參數(shù)的構(gòu)造函數(shù),具體實(shí)現(xiàn)例子如下

    public:Mystring(string x ) :m_string(x){cout << "Mystring 構(gòu)造函數(shù)調(diào)用了" << endl;}std::string m_string; };int main() { string z = "zzz";Mystring t = z; //隱式類型構(gòu)造函數(shù)就是一個(gè)參數(shù)的構(gòu)造函數(shù)return 0; }

    如果構(gòu)造函數(shù)前面加上explicit(明確的)可以阻止系統(tǒng)進(jìn)行改類型轉(zhuǎn)換。

    7.成員/虛/靜態(tài)函數(shù)指針 成員/靜態(tài)變量指針

    class MyT { public:void Test1(){cout << "普通成員函數(shù)調(diào)用" << endl;}static void Test2(){cout << "靜態(tài)成員函數(shù)調(diào)用" << endl;}virtual void Test3(){cout << "虛成員函數(shù)調(diào)用" << endl;}public:int m_a; //普通成員變量static int m_b; };int MyT::m_b = 1;int main() { MyT t;MyT * tp = &t;//1.普通成員函數(shù)//普通成員函數(shù)是跟著類走的,不是跟著對象走,只要有類,就能取到類成員函數(shù)的指針void (MyT::*myp)(void);myp = &MyT::Test1; (t.*myp)(); //前面必須拿圓括號括上,因?yàn)楹竺娴睦ㄌ杻?yōu)先級高!(tp->*myp)();//2.虛函數(shù) 與成員函數(shù)一致 必須綁定到類對象上void (MyT::*myp2) (void);myp2 = &MyT::Test3; (t.*myp2)();//3.靜態(tài)成員函數(shù)//不需要綁定到類對象上,可直接使用void (*myp3) (void);myp3 = &MyT::Test2;(*myp3)();//4.成員變量指針 不是某個(gè)地址 而是該成員變量與該類對象之間的偏移量int MyT::*myp4 = &MyT::m_a;//當(dāng)生成類對象時(shí),如果這個(gè)類中有虛函數(shù)表,就會有一個(gè)指向這個(gè)虛函數(shù)表的指針,這個(gè)指針占四個(gè)字節(jié)//所以這里看到的m_a的偏移是4,如果把 virtual 函數(shù)注釋后調(diào)試模式下查看myp4的值就會是0而不是0x4t.*myp4 = 111; // 等價(jià)于 t.m_a = 111;std::cout << t.m_a << endl;//靜態(tài)成員變量int *myp5 = &MyT::m_b;*myp5 = 111;return 0; }

    8.字節(jié)對齊問題
    定義一個(gè)結(jié)構(gòu)體如下

    typedef struct Student {char A; char B; int64_t D;char C; };

    按照常規(guī)的理解,其sizeof的結(jié)果應(yīng)該是11個(gè)字節(jié),但是我在64位機(jī)器上sizeof出來是24?為什么呢?看一下內(nèi)存分布

    0x0113FBFC是對象的初始地址,可以看到A和B分別占用了一個(gè)字,D占用了八個(gè)字節(jié),后面的C也占用了8個(gè)字節(jié),最后末尾還有7個(gè)字節(jié)。首先看看百度百科對于字節(jié)對齊規(guī)則的描述
    1) 結(jié)構(gòu)體變量的首地址能夠被其最寬基本類型成員的大小所整除;
    2) 結(jié)構(gòu)體每個(gè)成員相對于結(jié)構(gòu)體首地址的偏移量都是成員大小的整數(shù)倍,如有需要編譯器會在成員之間加上填充字節(jié)(?);
    3) 結(jié)構(gòu)體的總大小為結(jié)構(gòu)體最寬基本類型成員大小的整數(shù)倍,如有需要編譯器會在最末一個(gè)成員之后加上填充字節(jié)。(最后7個(gè)字節(jié)的來源)

    在這個(gè)結(jié)構(gòu)體的定義前后加上以下定義,就會發(fā)現(xiàn)sizeof大小為11,說明取消了默認(rèn)的字節(jié)對齊。這里這個(gè)語句的意思就是,接下來的結(jié)構(gòu)體定義,都按照n字節(jié)對齊,除去所有的padding字節(jié)。使內(nèi)存更加緊湊,節(jié)約內(nèi)存。

    #pragma pack(push,1) typedef struct Student {char A; char B; int64_t D;char C; }; #pragma pack(pop)

    9.malloc庫函數(shù)可能出現(xiàn)的問題以及改進(jìn)方法?
    malloc是線程不安全的,有可能出現(xiàn)分配異常的問題,自定義一個(gè)函數(shù)

    int malloclen= 0; void *ts_malloc( size_t blksize ) {void *blkaddr;static pthread_mutex_tmalloc_lock = PTHREAD_MUTEX_INITIALIZER;pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock,(void *)&malloc_lock );pthread_mutex_lock( &malloc_lock );malloclen += blksize;blkaddr = malloc( blksize );pthread_cleanup_pop( 1 );return( blkaddr ); }

    10.new 和 delete的使用
    new和delete成對使用
    且 new [] 與delete[]應(yīng)該對應(yīng)使用
    如果是內(nèi)部數(shù)據(jù)類型 如 int char操作時(shí)不會內(nèi)存泄漏,但是是自定義的類如果在new時(shí)用new[] 但是delete時(shí)用delete,則會出現(xiàn)內(nèi)存泄漏。多出的內(nèi)存是用來存儲在初始化時(shí)分配了幾個(gè)數(shù)組元素,一般多出的內(nèi)存是4個(gè)字節(jié)。
    自定義的類如果沒有自定義的析構(gòu)函數(shù),那么用delete也不會有內(nèi)存泄漏。
    為什么像 int 這種內(nèi)部數(shù)據(jù)類型不用額外的4字節(jié)?

    11.智能指針自定義刪除器
    //shared_ptr

    class Socket { public:Socket(){}~Socket(){}//關(guān)閉資源句柄void close(){//dosomething,such as close socket fd;} };

    自定義刪除器方式1

    std::shared_ptr<Socket> ptsocket(new Socket(),[](Socket * socket){socket->close();delete socket;})

    自定義刪除其方式2

    std::unique_ptr<Socket, void(*)(Socket * socket)> ptsocket(new Socket(), [](Socket * socket) { //to do });

    自定義刪除器方式3

    auto deletor = [](Socket* pSocket) {//關(guān)閉句柄pSocket->close();//TODO: 你甚至可以在這里打印一行日志...delete pSocket;};//std::unique_ptr<Socket, void(*)(Socket * pSocket)> spSocket(new Socket(), deletor);std::unique_ptr<Socket, decltype(deletor)> spSocket(new Socket(), deletor);

    后面的delete函數(shù)用Lambda表達(dá)式實(shí)現(xiàn)了
    shared_ptr和unique_ptr的刪除器實(shí)現(xiàn)方式不一樣,在傳遞模板參數(shù)時(shí),unique_ptr還需要傳遞一個(gè)刪除器的類型,因此類實(shí)現(xiàn)也就不一樣,會導(dǎo)致不同刪除器類型的unique_ptr不能放置于同一個(gè)容器中。而shared_prt則不一樣,只要指向的對象一樣,即使刪除器不一樣,也能放置于同一個(gè)容器中。
    詳解:王建偉C++ 5-7 00:30:32
    12.對象的生命周期
    以前一直覺得,函數(shù)執(zhí)行結(jié)束了,對象的生命周期才會結(jié)束,但是最近因?yàn)榭匆粋€(gè)bug才尼瑪知道,if while do while () 這些東西里面聲明的對象在出其作用域的時(shí)候都會釋放掉。

    #include <iostream> #include <stdio.h> using namespace std; int main() {if (1 == 1){int* p1;}*p1 = 11;while (nullptr == nullptr){auto p2 = (int)13;int p3 = 14;break;}cout << "p2 = " << p2 << endl;cout << "p4 = " << p4 << endl;for (int p5 = 0; p5 < 10; p5++){}p5 = 0;return 0; }

    以上程序在作用外均無法使用對象,對象與函數(shù)出棧時(shí)一樣,都已經(jīng)被釋放掉了…
    13.指針的長度
    普通的裸指針是 四字節(jié)
    shared_ptr 與 weak_ptr 是八個(gè)字節(jié),多出來的四個(gè)字節(jié)是用來存放指向控制塊的指針(包括 強(qiáng)引用計(jì)數(shù) 弱引用計(jì)數(shù) 自定義刪除器指針),實(shí)際上智能指針也就是存放了兩個(gè)裸指針。
    另外 unique_ptr 的尺寸與前兩個(gè)都不一樣
    unique_ptr p1(new string(“hello world!”));
    sizeof(p1) // 輸出結(jié)果是4 。。
    為什么unique_ptr是四個(gè)字節(jié)呢?因?yàn)闆]有自定義刪除器,如果增加了自己的刪除器,則 unique_ptr 的尺寸可能增加,比如傳遞函數(shù)指針類型時(shí)
    14.裸指針初始化只能指針陷阱

    int *p = new int(11);shared_ptr<int> p1(p);shared_ptr<int> p2(p);

    利用裸指針同時(shí)初始化兩個(gè)智能指針,會發(fā)現(xiàn)p1和p2的強(qiáng)引用都是1,釋放時(shí)會釋放兩次。
    15.循環(huán)引用導(dǎo)致的智能指針無法釋放

    class CB; class CA; class CB { public:std::shared_ptr<CA> pca; }; class CA { public:std::shared_ptr<CB> pcb; }; std::shared_ptr<CA> pca(new CA); std::shared_ptr<CB> pcb(new CB); pca->pcb = pcb; pcb->pca = pca;

    new了兩個(gè)對象,等于申請了兩塊內(nèi)存,但是pca的成員pcb是利用pcb創(chuàng)建的,會導(dǎo)致pca的強(qiáng)引用加1,同理 pcb的成員pca是利用pca創(chuàng)建的,會導(dǎo)致pcb的強(qiáng)引用也加1,所以在pca和pcb退出作用域時(shí),不會釋放其指向的內(nèi)存。
    15.智能指針設(shè)計(jì)的目的以及auto_ptr被放棄的原因
    防止內(nèi)存泄漏,休業(yè)式RAII的一種提現(xiàn)。
    auto_ptr使用缺陷是

    auto_ptr<string> p1 = new string("zzz"); auto_ptr<string> p2 = p1;

    這里定義會導(dǎo)致p1自動被釋放,造成不可預(yù)計(jì)的問題
    雖然unique_ptr也是獨(dú)占式的指針,但是unique_ptr會在編譯時(shí)報(bào)錯(cuò),編譯器不允許存在這種操作,避免后續(xù)使用p1導(dǎo)致的程序崩潰問題。
    16.死鎖的出現(xiàn)以及規(guī)避的方法
    同一個(gè)線程存在對兩個(gè)及兩個(gè)以上的鎖同時(shí)操作時(shí),有可能出現(xiàn)死鎖的情況。比較簡單的方案就是保證調(diào)用的順序來保證不出現(xiàn)死鎖的情況,另外,std下提供了lock方法,如

    std::lock(mutex1,mutex2); std::unlock(mutex1); std::unlock(mutex2);

    這個(gè)方法會一直嘗試獲取1鎖與2鎖,如果獲取不到又會釋放等待下一次獲取。
    上述方法有一點(diǎn)不好的就是沒有用到lock_guard,如下可以解決該問題。

    std::lock(mutex1,mutex2); std::lock_guard<std::mutex> guard1(mutex1,std::adopt_lock); std::lock_guard<std::mutex> guard2(mutex2,std::adopt_lock);

    使用adopt_lock關(guān)鍵字會使得guard對象在生成時(shí)不直接調(diào)用加鎖,而且后面也不用手動釋放鎖,脫離作用域自動釋放。

    17.為什么字符串在網(wǎng)絡(luò)傳輸不需要大小端轉(zhuǎn)換,而像int/long…等卻需要轉(zhuǎn)換?
    首先
    大端模式,是指數(shù)據(jù)的高字節(jié)保存在內(nèi)存的低地址中
    小端模式,是指數(shù)據(jù)的高字節(jié)保存在內(nèi)存的高地址中
    大端模式與人類的識別方式是相似的,從左往右,從高到底開始寫

    大小端是指在一個(gè)字節(jié)內(nèi),數(shù)據(jù)存儲的不同順序,以32位小端為例
    char a = 65; (字符A)a 在內(nèi)存中的存儲形式是
    0x1000 0010 0000 0000
    如果是大端模式,那么在內(nèi)存中的存儲形式是
    0x0000 0000 0100 0001
    //未驗(yàn)證 待驗(yàn)證

    18.dynamic_cast 和 static_cast 的區(qū)別

    static_cast屬于靜態(tài)類型的轉(zhuǎn)換,會在編譯的時(shí)候進(jìn)行類型檢查。
    可以用于相關(guān)類型的轉(zhuǎn)換,比如int和double之間的轉(zhuǎn)換,子類轉(zhuǎn)成父類,void*和其他類型之間的轉(zhuǎn)換,一般不能用于指針類型之間的互轉(zhuǎn)。從我的角度來看,static_cast就比C的強(qiáng)制類型轉(zhuǎn)換的作用稍微弱一點(diǎn),加了一些類型之間轉(zhuǎn)換的限制。

    dynamic_cast主要是具有運(yùn)行時(shí)檢查功能,轉(zhuǎn)換也是在運(yùn)行時(shí)轉(zhuǎn)換的,比如有三個(gè)類 基類是 human man 和women類分別繼承自 human
    有如下轉(zhuǎn)換,而且human必須具有虛函數(shù),否則dynamic_cast無法正常使用,只有虛函數(shù)的存在,才使用指針或引用所指向?qū)ο蟮膭討B(tài)類型。基類有虛函數(shù)之后,會有一個(gè)指針指向基類的虛函數(shù)表,

    human* A = new man; man* B = dynamic_cast<man> A; women* C = dynamic_cast<women> A;

    以上代碼在轉(zhuǎn)換時(shí),將A轉(zhuǎn)換成 women* 時(shí),因?yàn)閐ynamic_cast 屬于具有運(yùn)行時(shí)檢查功能,他發(fā)現(xiàn)A 指針實(shí)際上不是指向的一個(gè)women類時(shí),轉(zhuǎn)換就會失敗,得到的C是一個(gè)空指針。

    另外還有兩種強(qiáng)制類型轉(zhuǎn)換
    const_cast 和 reinterpret_cast

    const_cast 用于去除指針或者引用的常量屬性,屬于編譯時(shí)類型轉(zhuǎn)換。
    常見錯(cuò)誤使用

    const int a = 10;const int* p1 = &a;int* p2 = const_cast<int*>(p1);*p2 = 100;std::cout << a << std::endl;;

    reinterpret_cast 編譯時(shí)進(jìn)行的類型轉(zhuǎn)換
    重新解釋,把操作數(shù)的類型解釋為另外一種類型,處理無關(guān)類型的轉(zhuǎn)換。
    比如下面這個(gè)轉(zhuǎn)換,除了C里面的強(qiáng)制類型轉(zhuǎn)換能做到,其他的dynamic_cast static_cast const_cast均無法實(shí)現(xiàn)轉(zhuǎn)換,編譯無法通過。

    char* p = (char *)calloc(1, 1024);Message* pmessage = reinterpret_cast<Message*> (p);

    19.引用和指針有何區(qū)別?怎么拿到引用變量的地址?
    引用和指針本無區(qū)別,只是編譯器為了方便設(shè)置的語法糖,引用本身也是存儲了指向?qū)ο蟮闹羔樧兞?#xff0c;和 利用 & 取到的變量地址沒有任何差別,只是看起來不一樣。
    至于怎么拿地址?似乎引用變量沒有占內(nèi)存啊?
    參考文
    引用比指針安全么?也不是,一樣也存在安全問題,僅僅就是一個(gè)語法糖而已

    int *var = new int(42); int &ref = *var; delete var; ref = 42; return 0;

    為了進(jìn)一步驗(yàn)證引用與指針在本質(zhì)上的相同,我們看當(dāng)引用作為函數(shù)參數(shù)傳遞時(shí),編譯器的行為:

    1 void Swap(int& v1, int& v2); 2 void Swap(int* v1, int* v2);3 4 int var1 = 1; 5 00A64AF8 mov dword ptr [var1],1 6 int var2 = 2; 7 00A64AFF mov dword ptr [var2],2 8 Swap(var1,var2); 9 00A64B06 lea eax,[var2] 10 00A64B09 push eax 11 00A64B0A lea ecx,[var1] 12 00A64B0D push ecx 13 00A64B0E call Swap (0A6141Fh) 14 00A64B13 add esp,8 15 Swap(&var1, &var2); 16 00A64B16 lea eax,[var2] 17 00A64B19 push eax 18 00A64B1A lea ecx,[var1] 19 00A64B1D push ecx 20 00A64B1E call Swap (0A61424h) 21 00A64B23 add esp,8

    上面代碼再次證明了,引用與指針的行為完全一致,只是編譯器在編譯時(shí)對引用作了更嚴(yán)格的限制。
    不要用匯編結(jié)果來替代概念,引用不占空間意思就是不占對象空間,不表示不占指針的少量空間。實(shí)際上指針是匯編工具實(shí)現(xiàn)引用的一種方式而已,而有的優(yōu)化結(jié)果可能沒有代表自己的指針。
    總而言之,引用就是引用,是這種概念,它為方便程序員使用,和方便匯編工具優(yōu)化而產(chǎn)生。匯編怎么實(shí)現(xiàn)和優(yōu)化是匯編的事,至于出了什么違反該概念的結(jié)果,是匯編的錯(cuò),而不是定義的錯(cuò),不要本末倒置。
    你可以通過匯編來了解編譯器怎樣實(shí)現(xiàn)引用
    引用 卻不應(yīng)該用匯編來解釋 它只是一個(gè)概念
    贊同,引用只是編譯器之上,給出來的一個(gè)抽象定義。接口的實(shí)現(xiàn),由編譯器來決定!
    仔細(xì)想想,確實(shí)如此,引用只是一個(gè)概念,為我們提供了一個(gè)接口。怎么實(shí)現(xiàn),由編譯器自己決定。

    20.RTTI是什么東西?
    run time type identification :運(yùn)行時(shí)類型檢查
    利用dynamic_cast將基類的指針或引用安全的轉(zhuǎn)換成子類的指針或者引用,并用來調(diào)用子類的某個(gè)重寫的虛函數(shù)。

    21.獲取開機(jī)到現(xiàn)在的時(shí)間函數(shù)

    extern int clock_gettime (clockid_t __clock_id, struct timespec *__tp) __THROW;

    22.git相關(guān)
    撤銷已a(bǔ)dd的單個(gè)文件修改到modified

    git reset 單個(gè)文件名

    撤銷已commit的某個(gè)文件的修改
    首先查詢這個(gè)文件的log:

    git log <fileName>

    其次查找到這個(gè)文件的上次commit id xxx,并對其進(jìn)行reset操作:

    git reset <commit-id> <fileName>

    再撤銷對此文件的修改:

    git checkout <fileName>

    最后amend一下,再push上去:

    總結(jié)

    以上是生活随笔為你收集整理的大-杂-烩的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。