鍍金池/ 問答/ C++問答
綰青絲 回答
c 語言的 宏 是自動根據(jù)值來確定類型的??

宏是不帶類型信息的, 只是preprocessor的一個文本替換的, 與之相對的c++的模板則帶有類型信息.

請問 宏 的實際應(yīng)用價值是什么??

原理


簡單的說, 就是文本替換, 只不過基于文本替換可以玩出來些花樣.

實際應(yīng)用價值


性能 能省去函數(shù)調(diào)用的開銷, 實現(xiàn)真正意義上的inline.

實現(xiàn)泛型與重載 c是不支持這倆貨的, 一定層面, 宏可以實現(xiàn)其功能, 很經(jīng)典的一個例子: #define max(a,b) ((a)<(b)?(b):(a)), 可以傳int, float等等, 你可以理解為支持了重載, 也可以理解為支持了泛型, 雖然很丑陋233. 再舉個不那么常見的:

#define MAKE_PAIR(T) \
  typedef struct MAKE_PAIR##T{ \
       T first; \
       T second; \
  } ##T##_pair 

 MAKE_PAIR(char);
 MAKE_PAIR(int);
 MAKE_PAIR(float);

這樣就直接定義了多個類型的pair. 也是對泛型的模擬.

我感覺他和 變量 的作用是一樣的..,而且相比變量感覺由于沒有聲明數(shù)據(jù)類型,在使用上更加不方便...

就是不方便呀, 而且不只是缺乏類型, 更重要的是它的scope是dynamic scope, 而不是大家所熟知的lexical scope, 前者的name lookup是在調(diào)用處尋找, 而后者則是在定義處. 這有時候會造成混亂.

什么時候可以用?

  • 自己瞎玩時
  • 確定下來真的是某個函數(shù)是性能瓶頸(這種情況其實很少出現(xiàn))

什么時候不該用?

能不用的時候就別用

Update

回復(fù)OP的疑問: 你給的這兩個鏈接的說法都不對. inline這個keyword和語義inline本身無關(guān), 你添加了inline其實不會對編譯器有什么影響. 編譯器有自己的判斷. c的inline是c99開始出現(xiàn)的, 貌似是學(xué)c++的. c語言的odr(或者說c其實是沒有odr的, 這里只是代指那套規(guī)則)我不是很熟悉, 不過在c++里面inline關(guān)鍵詞的作用就是屏蔽odr檢查. 和inline的語義(內(nèi)聯(lián))沒有任何關(guān)系. 泛型的話也別看百度百科, 里面問題一大堆. 多搜英文資料. 或者寫寫c++的模板就知道了. 上面那個pair應(yīng)該還是很容易看出泛型在c里面的應(yīng)用的. 不只是primitive type, 其實你自己的結(jié)構(gòu)體也可以這樣很輕松的做出搞出來pair.

念舊 回答

合法。不合理。data1可能不會是你預(yù)想中的數(shù)據(jù)

墨小白 回答

常量區(qū),屬于常量字符串。

憶往昔 回答

inspect只是為了查看容器里面的值的時候用的,你這里沒有調(diào)用,當(dāng)然也不會執(zhí)行

夢若殤 回答

你可以查一下vue單文件組件,這也是項目中最常使用的組件組織形式。

傻叼 回答

在C++里使用C庫的函數(shù)時,你加了 extern "C" { } 嗎? 否則就會鏈接找不到。

笨笨噠 回答

今天把Vue的代碼和jQuery的代碼分開成兩個<script>,好像好了

在form上加上onsubmit="return false;"解決了,原來這個報錯不是
$.ajax({

            type: "POST",。。。。
           

導(dǎo)致的

焚音 回答

函數(shù)呼叫, invoke/call, 就是你調(diào)用函數(shù)的那個語句.

函式宣告, 即declaration, 與definition相對, 前者是后者的超集, 所以每一個definition都是一個declaration, 而definition不一定是declaration:

clipboard.png

簡而言之, definition是definition的超集, definition是declaration的子集, 所以是one definition ruler, 而不是one declaration ruler

維他命 回答

標(biāo)準(zhǔn)約定std::thread構(gòu)造時向函數(shù)對象傳遞實際參數(shù)的拷貝(支持移動語義),而不是轉(zhuǎn)發(fā)實際參數(shù)(你可以通過打印實際參數(shù)和形式參數(shù)的地址來檢測這一行為)。即fun的形式參數(shù)是被a的拷貝初始化的,所以形式參數(shù)a并不是main函數(shù)內(nèi)a的引用,在fun內(nèi)賦值自然不會改變main函數(shù)內(nèi)a的值。

如果你希望“以引用的方式傳參”,常用解決方案之一是使用std::ref,即std::thread(fun, std::ref(a));。

真難過 回答

如 sserver 日志所示

 15 E0403 17:24:39.589262  4886 Utils.cc:221] unable to request data from: https://127.0.0.1/get_user_id_list?last_id=0, error: Couldn't connect to server
 16 E0403 17:24:39.589727  4886 StratumServer.cc:480] http get request user list fail, url: https://127.0.0.1/get_user_id_list?last_id=0
 17 E0403 17:24:39.589777  4886 StratumServer.cc:547] update user list failure
 18 E0403 17:24:39.589867  4886 StratumServer.cc:776] fail to setup server
 19 F0403 17:24:39.589912  4886 StratumServerMain.cc:171] init failure

參考 sserver.cfg 的注釋,你需要自己搭建一個網(wǎng)站服務(wù)器(xx.yy),并提供一個網(wǎng)站接口(/get_user_id_list),然后把網(wǎng)址寫入 sserver.cfg 文件的 list_id_api_url 項,如下

users = {
    list_id_api_url = "http://xx.yy/get_user_id_list";
};

你可以在本機搭建一個 apache 或者 nginx 服務(wù)器,然后按照
https://github.com/btccom/btc...
上的說明操作便可。

清夢 回答

強引用計數(shù)(uses)為0時會析構(gòu)對象,弱引用計數(shù)(weaks)為0時會刪除ref counter對象,所以創(chuàng)建shared_ptr都會有一個uses和一個weaks

網(wǎng)妓 回答

答案來了。

const axios = require('axios')
// 下面代碼發(fā)送一個post請求到一個服務(wù)器
axios.post('驗證驗證碼的目標(biāo)url', {
    telephone: "17202345234" // 帶上手機號參數(shù)
  })
  .then(function (response) { // 后端處理成功,給你返回一個驗證碼數(shù)據(jù),數(shù)據(jù)通過response讀取
    console.log(response.testnumber);
    return axios.post('獲取驗證碼成功再發(fā)送一次請求的地址',{
        password: "我是密碼",
        telephone: "17202345234",
        noteinfo: "我是備注"
    })
  })
  .then(function(res){
    //完成注冊了
    console.log("注冊完成");
   })
  .catch(function (error) { // 如果請求失敗就走這里了
    console.log(error);
  });
心沉 回答

打開藍牙的HCI log ,抓取hci log 看看通訊情況 ,hci log 可以用 wireshark 軟件查看 hci log文件一般會保存SD卡目錄下,也有的手機保持其他路徑,可以找 /etc下的藍牙配置文件查看保持路徑

情皺 回答

可重入鎖不是這么用的,一般是在面向?qū)ο笾惺褂茫热?/p>

class A:
   def f1(self):
       mutex.acquire()
       try:
           #do something
       finally:
           mutex.release()
   def f2(self):
       mutex.acquire()
       try:
           #do something
       finally:
           mutex.release()

def run1(obj):
    obj.f1()
    obj.f2()
    
def run2(obj):
    obj.f2()
    obj.f1()

obj1 = A()
t1 = threading.Thread(target=run1, args=(obj1, ))
t2 = threading.Thread(target=run2, args=(obj1, ))
t1.start()
t2.start()

調(diào)用順序不同,而且都需要同步的時候,如果不用遞歸鎖,會死鎖。如果f1或f2不加鎖,數(shù)據(jù)不同步,報錯

維她命 回答

if (!file)
{

cout << "文件打開失敗" << endl;

}
for (int i = 0; i < t; i++)
{

file.write((char*)&book[i], sizeof(book[i]));

}
這里打開文件, 你的程序仍然會嘗試執(zhí)行for里面的內(nèi)容, 就會導(dǎo)致指針錯誤了. 應(yīng)該是在退出后 不但要結(jié)束while循環(huán), 還應(yīng)該退出函數(shù), 不應(yīng)該繼續(xù)執(zhí)行while后面的語話.

我以為 回答

說下自己的理解,供參考。假設(shè)題主了解網(wǎng)絡(luò)編程和計算機系統(tǒng)的一些基本概念。

簡單概括來說,事件驅(qū)動是實現(xiàn)并發(fā)處理的一種方式。

我們就以HTTP請求的處理過程為例,為簡化說明,僅考慮網(wǎng)絡(luò)IO,不考慮文件IO和數(shù)據(jù)庫等其他過程,也不考慮多核系統(tǒng)。
考慮采用如下最簡模型來處理HTTP請求:

main_loop:
  accept() 
  recv()  
  parse() 
  send() 
  close() 

來一個連接,讀取數(shù)據(jù)(請求),解析請求內(nèi)容,返回數(shù)據(jù)(應(yīng)答)。
同一時間只為一個客戶端服務(wù)。在為A客戶端服務(wù)的過程中,B客戶端必須等待。

這種方式非常簡單直接,容易理解,但其無法滿足現(xiàn)實場景的需要——不支持并發(fā)。
現(xiàn)實中,客戶端的請求是并發(fā)的:即當(dāng)一個客戶端的請求還在處理時,另外一個客戶端的請求就會達到,甚至多個客戶端的請求同時達到。
而且,recv 和 send等涉及網(wǎng)絡(luò)操作的API由于網(wǎng)絡(luò)數(shù)據(jù)發(fā)送與到達的不確定性,可能需要等待,CPU會空閑下來——但這種模型下即使CPU空閑了也無法處理其他客戶端的請求,浪費了CPU。

我們采用如下多線程模型,可以解決上述問題:

main_loop:
  accept() 
  start_thread(thread_loop)

thread_loop:    
    recv()  
    parse() 
    send() 
    close() 
    exit thread()

即每個客戶端在一個獨立的線程中處理。
當(dāng)一個客戶端的線程執(zhí)行網(wǎng)絡(luò)操作需要等待時,會被操作系統(tǒng)調(diào)度出去,執(zhí)行其他需要干活兒的線程。
似乎完美了解決了我們的問題?
然而并沒有。
因為操作系統(tǒng)創(chuàng)建線程的開銷是比較大的,能夠支持的線程數(shù)量是有限的,通常是幾萬的級別,如果線程太多,就會有很多的CPU浪費在了線程的創(chuàng)建、銷毀、調(diào)度等管理操作上。

所以為了充分發(fā)揮CPU的能力,支持更多的并發(fā)數(shù)量,,在Linux上有另外一種處理并發(fā)的方式:
內(nèi)核提供了監(jiān)聽大量網(wǎng)絡(luò)連接(句柄)可讀、可寫等事件的機制和接口。
應(yīng)用把需要監(jiān)聽對象以及關(guān)心的事件注冊給內(nèi)核,內(nèi)核在有事件達到時通知應(yīng)用處理。
基于這種機制處理并發(fā)就是事件驅(qū)動。

事件驅(qū)動機制的基本模型是:

create_listen_socket()
register_event_for_listen_socket()
main_loop:
    wait_for_event()
    check_events:
         if listen_socket has event(new client coming) :
               accept()
               register_event_for_client_socket()
        if client_socket has event(new data coming):
               recv()                       
               parse()
               send()              

但這里有一個問題,有可能一個客戶端剛讀取了一部分?jǐn)?shù)據(jù),就沒了,剩下的還在網(wǎng)絡(luò)中沒過來,需要繼續(xù)等待。
這就需要把當(dāng)前的讀取內(nèi)容和請求處理狀態(tài)(也即上下文)保存起來,繼續(xù)處理其他客戶端的事件。
然后下次這個客戶端再有事件到來時再找回上下文繼續(xù)處理。
這其實需要應(yīng)用自己做一些任務(wù)調(diào)度相關(guān)的上下文保存和切換工作。

當(dāng)使用多線程處理并發(fā)時,操作系統(tǒng)幫我們做了這些工作,我們無需關(guān)心任務(wù)切換。
因為一個線程就只處理一個客戶端,反復(fù)調(diào)用recv把一個請求的數(shù)據(jù)讀完然后解析處理就可以了,也不用擔(dān)心沒數(shù)據(jù)到來時,recv阻塞了其他客戶端的處理。
所以多線程編寫并發(fā)代碼非常簡單直接。

如上,事件驅(qū)動機制是Linux上解決并發(fā)問題的一種高效編程模型。
應(yīng)用反復(fù)探測事件,對接收到的事件進行逐個處理的過程就是事件循環(huán)。

那么同步和異步概念體現(xiàn)在哪里呢?

所謂同步就是我們執(zhí)行一個任務(wù),一直等待任務(wù)執(zhí)行結(jié)束。
所謂異步就是我們執(zhí)行一個任務(wù),不等待任務(wù)執(zhí)行結(jié)束,繼續(xù)去干其他活兒,任務(wù)結(jié)果后有個通知,或者干脆不關(guān)心任務(wù)的執(zhí)行結(jié)果。

在多線程模型中,每接收到一個新的客戶端就創(chuàng)建一個線程處理,這就是一種異步處理。
在事件驅(qū)動模型中,當(dāng)沒有數(shù)據(jù)可讀時,就把這個客戶端繼續(xù)放到監(jiān)聽隊列中監(jiān)聽,也是一種異步。

如果我們考慮文件IO,把IO請求丟給另外一個或一組線程(線程池)處理,處理完后通知主線程,也是一種異步。

黑與白 回答

路徑改成
val bankText = sc.textFile("file:\\D:/Projects/Zeppelin/bank/bank-full.csv")

喜歡你 回答

應(yīng)該用celery起異步任務(wù)做

護她命 回答

你這樣同時發(fā)送三個請求到一個接口,真的是太耗費網(wǎng)絡(luò)資源了。請求接口,網(wǎng)絡(luò)連接,接口響應(yīng) 都需要時間。

我覺得,你可以跟后端開發(fā)商量,添加一種傳參方式。

目前,你傳的是單個對象,你可以讓后端添加一種傳遞數(shù)組的方式,數(shù)組里包含 N 個你想獲取的數(shù)據(jù)參數(shù)。

(手機打字,有問題請回復(fù)我......)

傲寒 回答

CURLOPT_SSL_VERIFYPEER 新版php中默認(rèn)是2