[英]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*
指針作為參數,並導致未定義的行為。 它相當於傳遞0
或NULL
:
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++ 14
或C++17
或C++11
,這種未定義的行為會導致clang5.0
和gcc7.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.