簡體   English   中英

C ++對象構造方法的區別

[英]Difference between C++ object construction methods

C ++中不同的構造語法總是讓我感到困惑。 另一個問題中 ,有人建議嘗試初始化一個字符串

std::string foo{ '\0' };

這有效並產生預期結果:長度為1的字符串僅包含空字符。 在測試代​​碼時,我不小心輸入了

std::string foo('\0');

這編譯很好(即使使用-Wall沒有警告),但在運行時終止

terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_M_construct null not valid
Aborted (core dumped)

現在,據我所知, 沒有 std::string 構造函數 ,它將一個字符作為參數,當我嘗試間接傳遞該字符時,這個假設得到進一步證實。

char b = '\0';
std::string a(b);

這會產生一個很好的,冗長的編譯錯誤。 就像這樣

std::string a('z');

所以我的問題是:什么允許std::string a('\\0'); 編譯,以及它與std::string a{ '\\0' };


腳注:在Ubuntu上使用g++進行編譯。 這並沒有把我當作編譯器錯誤,但以防萬一......

字符'\\0'可隱式轉換為0整數值,從而表示實現定義的空指針常量 這個:

std::string foo('\0');

調用構造函數重載接受類型為const char*指針作為參數,並導致未定義的行為。 它相當於傳遞0NULL

std::string foo(0); // UB
std::string bar(NULL); // UB

第4和第5個構造函數的引用重載狀態:

如果s ...行為是未定義的,包括s是空指針的情況

第二個聲明:

std::string foo{'\0'}; // OK

調用構造函數接受std::initializer_list<char>作為參數,並且不會導致UB。

您可以調用構造函數重載來接受char計數數量:

std::string s(1, '\0');

對於C++ 14C++17C++11 ,這種未定義的行為會導致clang5.0gcc7.2中的編譯錯誤。

#include<string> 
std::string S('\0');

錯誤:沒有匹配函數來調用'std :: __ cxx11 :: basic_string :: basic_string(char)'std :: string S('\\ 0'); ^

在最近的編譯器版本中,UB是固定的(以產生編譯器錯誤)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM