2009-10-19 77 views
9

我有一個請求方法需要std::streambuf*的網絡客戶端。這種方法是由boost::iostreams::copy實現的 - 它是一個定製的std::streambuf派生類,它知道如何將數據寫入網絡API,這非常有效。這意味着我可以將文件流式傳輸到請求中,而無需將其全部讀取到內存中。從std :: string流沒有複製?

但是,在某些情況下,必須發送不在文件中的大塊數據,所以我包含了一個需要字符串的重載。爲了避免重複流中的所有網絡代碼,似乎很明顯我應該設置代表該字符串的streambuf並調用其他方法。我能想出使這項工作的唯一辦法是這樣的:

std::istringstream ss(data); 
send(ss.rdbuf()); 

不幸的是,istringstream使得數據,在某些情況下是幾兆字節的副本。在一般情況下,它是非常有意義的,當然,如果您將一個const引用傳遞給某個對象,那麼您不希望該對象繼續使用該引用。

我工作圍繞這與以下:

struct zerocopy_istringbuf 
    : public std::stringbuf 
{ 
    zerocopy_istringbuf(std::string const* s) 
     : std::stringbuf(std::ios::in) 
    { 
     char* p = const_cast<char*>(s->c_str()); 
     setg(p, p, p + s->length()); 
    } 
}; 

... 

send(&zerocopy_istringbuf(data)); 

這似乎是工作得很好,但我不知道是否真的有必要。爲什麼std::istringstream超負荷需要std::string const *?有一個更好的方法嗎?

回答

4

你有這些問題的原因是,std :: string並不真正適合你在做什麼。更好的想法是在傳遞原始數據時使用char向量。如果可能的話,我只是改變一切使用矢量,使用vector :: swap和引用矢量作爲appropriatte來消除所有的複製。如果你喜歡iostreams/streambuf api,或者你需要處理一些需要streambuf的東西,那麼創建你自己的使用vector的streambuf是很簡單的,就像你的一樣。它將有效地做與你在其他答案中列出的相同問題一樣的事情,但你不會違反班級的合同。否則,我認爲你所得到的可能是向前傳遞一個istringstream無處不在的最佳方式。

+0

一個有趣的想法。我喜歡現有設置的一件事是我可以通過派生自std :: stringbuf來設置自定義輸入或輸出流,我只需要重寫一個或兩個簡單的函數,下溢或「溢出」和「同步「,基類爲我處理所有的緩衝區管理。我懷疑,基於'std :: vector'的東西意味着我需要更多的代碼。無論如何,我可能會使用'swap',儘管我需要讓調用者「放棄」字符串而不是傳入一個常量引用。 – 2009-10-19 18:29:26

2

imho,最好的選擇是不贊成的類std :: strstream

+0

謝謝,我不知道這件事。唯一的問題是它需要'char *'而不是'const char *',但這很容易解決。 – 2010-07-08 22:11:49

相關問題