2016-12-24 66 views
2

我想這個代碼中的最後兩行應該編譯。每當預期字符串文字時,可以使用std :: string :: c_str()嗎?

#include "rapidjson/document.h" 

int main(){ 
    using namespace rapidjson ; 
    using namespace std ; 

    Document doc ; 
    Value obj(kObjectType) ; 
    obj.AddMember("key", "value", doc.GetAllocator()) ; //this compiles fine 
    obj.AddMember("key", string("value").c_str(), doc.GetAllocator()) ; //this does not compile! 
} 

雖然我的猜測是錯誤的。一行編譯,另一行不行。

AddMember方法有幾個變種,如文檔here,但除此之外......爲什麼.c_str()的返回不等於字符串文字?

我的理解是,凡是字符串文字被接受的地方,你可以通過string::c_str(),它應該工作。

PS:我用VC++ 2010

編輯編譯:
缺乏#include <string>是沒有問題的。它已經被document.h

包含這是錯誤:

error C2664: 'rapidjson::GenericValue<Encoding> &rapidjson::GenericValue<Encoding>::AddMember(rapidjson::GenericValue<Encoding> &,rapidjson::GenericValue<Encoding> &,Allocator &)' 
: cannot convert parameter 1 from 'const char [4]' to 'rapidjson::GenericValue<Encoding> &' 
    with 
    [ 
     Encoding=rapidjson::UTF8<>, 
     Allocator=rapidjson::MemoryPoolAllocator<> 
    ] 
    and 
    [ 
     Encoding=rapidjson::UTF8<> 
    ] 

EDIT2:
請忽略的事實是.c_str()被稱爲一個時間值。這個例子只是爲了顯示編譯錯誤。實際的代碼使用一個字符串變量。


EDIT3:
代碼的替代版本:

string str("value") ; 
obj.AddMember("key", "value", doc.GetAllocator()) ; //compiles 
obj.AddMember("key", str, doc.GetAllocator()) ; // does not compile 
obj.AddMember("key", str.c_str(), doc.GetAllocator()) ; // does not compile 
+0

您是否包含''?而且,'main()'總是返回'int'。 –

+1

字符串文字具有數組類型,而'c_str()'返回一個指針。有可能會有功能超載,可以說明差異(但相當不友好,使他們的行爲顯着不同)。 –

+0

'string(「value」).c_str()'的生存期非常有限。所以除非'const char *'的副本完成,否則你可能有懸掛指針。 – Jarod42

回答

2

看着你鏈接到的文件,它似乎是你要撥打AddMember超過兩個StringRefType(和Allocator)。 StringRefTypeGenericStringRef<Ch>一個typedef,其具有兩個重載構造採取一個參數:

template<SizeType N> 
GenericStringRef(const CharType(&str)[N]) RAPIDJSON_NOEXCEPT; 

explicit GenericStringRef(const CharType *str); 

當通過一個字符串,類型是const char[N],其中N是串+ 1(對於空的長度終止)。這可以使用第一個構造函數重載隱式轉換爲GenericStringRef<Ch>。但是,std::string::c_str()返回const char*,由於第二個構造函數過載聲明爲explicit,因此無法將其隱式轉換爲GenericStringRef<Ch>

您從編譯器中獲得的錯誤消息是由於它選擇了另一個更接近匹配的過載AddMember而導致的。

+0

請注意,編譯器在引用的診斷中反應的實際參數是一個文字或數組,聲明爲'char const [4]',而不是c_str()調用。 –

+0

@ Cheersandhth.-Alf編譯器錯誤也是指參數1.因此,我的答案中的最後一句。 –

+0

好,所以基本上,'AddMember'方法接受字符串文字而不是'char'指針。 – GetFree

5

std::string::c_str()方法返回一個char const*。字符串文字的類型是char const[N],其中N是字符串中的字符數(包括空終止符)。相應地,c_str()的結果可以是而不是可用於全部可以使用字符串文字的地方!

但是,如果您嘗試呼叫的界面需要char陣列,我會感到驚訝。也就是說,在你使用它應該工作。這很可能需要包含<string>

+0

您也無法將c_str傳遞給期望char *(不是const),數組或不是的數組。而且你還必須小心,你傳遞給它的函數不會將指針存儲在某個地方以備後用,這會編譯但最終會炸燬。 –

+3

@JasonC:你無法將字符串字面值傳遞給期望char *的東西!特殊轉換的C向後兼容性總是被棄用,並且被C++ 11刪除。 –

3

即使該代碼編譯:

obj.AddMember("key2", string("value").c_str(), doc.GetAllocator()); 

你不能保證它是安全的。

std :: string :: c_str()返回的const char *將一直有效,直到此語句結束。

如果AddMember方法存儲字符串本身的副本,一切都很好。如果它存儲了一個指針,那麼你註定了。您需要了解AddMember的內部工作原理,然後才能推斷代碼的正確性。

我懷疑作者已經想到了這一點,並已構建了要求,你要麼在std::string對象(或同等學歷)發送過載或文字字符串引用(template<std::size_t N> void AddMember(const char (&str)[N])

即使這不是他們記住,他們可能希望保護你不受自己的影響,以防你無意中發出無效指針。

雖然看起來很不方便,但是這個編譯時錯誤表明一個可能出錯的程序。這是圖書館作者的致敬。因爲編譯時錯誤比運行時錯誤更有用。

+0

_您需要了解AddMember的內部工作原理,然後才能推斷您的代碼的正確性。 - - 您需要仔細閱讀文檔。但謹慎使用這種結構是一個很好的建議,我謹向圖書館的作者致敬。 –

2

重新

why is the return of .c_str() not equivalent to a string literal

甲文字串與在編譯時已知大小的陣列的零終止的字符串。

c_str()會生成一個指向(第一個項)的指針,該指針指向一個數組,其大小僅在運行時已知。

通常情況下,將在表達式衰減指向第一項的上下文中使用字符串文字表達式,但在某些特殊情況下,它不會衰減。這些情況包括

  • 結合到數組的引用,

  • 使用sizeof操作者,和

  • 形成字符串文字的較大字面由編譯時間級聯(僅僅是爲了將它們寫)。

我認爲這是一份詳盡的清單。


你引用的錯誤消息,

cannot convert parameter 1 from 'const char [4]' to 'rapidjson::GenericValue &

&hellip; 不符合您呈現代碼

#include "rapidjson/document.h" 

int main(){ 
    using namespace rapidjson ; 
    using namespace std ; 

    Document doc ; 
    Value obj(kObjectType) ; 
    obj.AddMember("key1", "value", doc.GetAllocator()) ; //this compiles fine 
    obj.AddMember("key2", string("value").c_str(), doc.GetAllocator()) ; //this does not compile! 
} 

無處在這段代碼有三個字符長的字符串文字。

因此該「這個編譯」和「這並不編譯」權利要求書,都不是很值得信賴的。

  • 應該引述實際的錯誤信息和實際代碼(其中至少有一個是不是你有什麼,當你編譯),並

  • 應該引述的文件你正在調用的函數。

此外,請注意,實際的論點,即編譯反應以在所列出的診斷,是文字或聲明爲這樣,不是c_str()呼叫的陣列。

+0

也許VC++不計算空終止? – GetFree

+0

@GetFree:它必須數它。它是數組大小的一部分。 –

+0

哦,你說得對,我剛剛意識到我在寫這個問題的時候在''key''字符串中加了一個''1「'和''2」'。我會解決這個問題。 – GetFree

相關問題