C++ Primer 答客問 (37) - reference, allocator

看板CompBook (電腦用書)作者時間25年前 (2000/02/24 16:48), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串1/1
C++ Primer 答客問 (37) - reference, allocator 侯捷 jjhou@ccca.nctu.edu.tw 2000.02.24 第一次發表於 清大.楓橋驛站(140.114.87.5).電腦書訊版(Computer/CompBook) 本文將於日後整理於 侯捷網站/侯捷譯作/C++ Primer 中文版/答客問 侯捷網站:www.jjhou.com ---------------------------------------------------------------- mfc42 wrote (2000/02/19) : > 侯老師您好: > 最近拜讀您的譯作〝C++ Primer 3/e〞時,發現有兩個問題, > 想要請教您,希望老師能為我解答,謝謝!不過我目前是學生, > 沒有要趕project的壓力,所以要是老師最近很忙的話,我的 > 這一封信可以等老師有空閒時再撥空幫我解答。 > > ================================================================== > 1.在書中p.108有介紹如何將一個reference的初值設為某個const object的 > 位址的方法,一開始看時也沒覺得有什麼奇怪的地方,但後來寫了一個 > 測試程式如下:(我使用的是VC6) > > void main() > { > const int ival = 1024; > int *const &pi_ref = &ival; > } > > 卻產生編譯錯誤: > > --------------------Configuration: test - Win32 Debug-------------------- > Compiling... > test.cpp > E:\Microsoft Visual Studio\Vc98\MyProjects\test\test.cpp(8) : > error C2440: 'initializing' : cannot convert from > 'const int *' to 'int *const & ' > Reason: cannot convert from 'const int *' to 'int *const ' > Conversion loses qualifiers > Error executing cl.exe. > > test.exe - 1 error(s), 0 warning(s) > > 我覺得很奇怪,明明是照書上打的,一字不漏呀!是不是應該要加什麼 > header file(s) 咧?而且照Stanley所用的解釋方法來解那一行程式:pi_ref > 是一個reference,也就是說pi_ref是要去代表某一個東西,是什麼東西呢? > 是一個常數指標,指向int object。也就是說常數指標一旦指向了一個object > ,其內容就不能再改變了,所以是int *const。但是在rvalue的部份:&ival是個 > const int object的位址。再怎麼樣解釋也是const int*呀!看起來... > 一定無法指派給pi_ref的嘛!是不是哪裡有問題咧? > > ================================================================== > 2.這是container的問題,在書中Stanley有提過allocator。不知VC6有沒有 > 支援 default template parameters。寫了一個測試程式: > > #include <vector> > #include <string> > > using namespace std; > > void main() > { > vector<string, allocator> svec; > } > > 結果有errors: > --------------------Configuration: test - Win32 Debug-------------------- > Compiling... > test.cpp > E:\Microsoft Visual Studio\Vc98\MyProjects\test\test.cpp(8) : error C2955: 'allocator' : use of class template requires template argument list > e:\microsoft visual studio\vc98\include\xmemory(72) : see declaration of 'allocator' > E:\Microsoft Visual Studio\Vc98\MyProjects\test\test.cpp(8) : error C2133: 'svec' : unknown size > E:\Microsoft Visual Studio\Vc98\MyProjects\test\test.cpp(8) : error C2512: 'vector<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::allocator>' : no appropriate default constructor available > E:\Microsoft Visual Studio\Vc98\MyProjects\test\test.cpp(8) : error C2262: 'svec' : cannot be destroyed > Error executing cl.exe. > > test.obj - 4 error(s), 0 warning(s) > > 如果不加allocator,則會有warnings: > > --------------------Configuration: test - Win32 Debug-------------------- > Compiling... > test.cpp > E:\Microsoft Visual Studio\Vc98\MyProjects\test\test.cpp(9) : warning C4786: 'std::reverse_iterator<std::basic_string<char,std::char_traits<char>,std::alloca tor<char> > const *,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std > ::basic_string<char,std::char_traits<char>,std::allocator<char> > const &,std::basic_string<char,std::char_traits<char>,std::allocator<char> > const *,int>' : identifier was truncated to '255' characters in the debug information > E:\Microsoft Visual Studio\Vc98\MyProjects\test\test.cpp(9) : warning C4786: 'std::reverse_iterator<std::basic_string<char,std::char_traits<char>,std::alloca tor<char> > *,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basi > c_string<char,std::char_traits<char>,std::allocator<char> > &,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,int>' : identifier was truncated to '255' characters in the debug information > e:\microsoft visual studio\vc98\include\vector(39) : warning C4786: 'std::vector<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<ch ar> > > >::vector<std > ::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<ch ar> > > >' : identifier was truncated to '255' characters in the debug information > e:\microsoft visual studio\vc98\include\vector(60) : warning C4786: 'std::vector<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<ch ar> > > >::~vector<st > d::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<ch ar> > > >' : identifier was truncated to '255' characters in the debug information > > test.obj - 0 error(s), 4 warning(s) > > 不過不管是error還是warning,我都看不懂它在說什麼,請老師告訴我 > 這部份該怎麼寫才好、才對呢? > > 以上兩個問題希望老師能為我解答,謝謝! 侯捷回覆: 你的第一個問題,關於 p108 範例,我以三種編譯器編譯結果如下 (希望你看得懂我的安排):(我的 g++ 是 2.91.57_on_win32) #01 #include <iostream> #02 using namespace std; #03 #04 int main() #05 { #06 const int ival = 1024; #07 #08 { // 情況 1 #09 int *&pi_ref = &ival; // 書上說這不可以. vc6[x] cb4[x] g++[o] #10 cout << pi_ref << endl; // 0x259fc90 #11 cout << *pi_ref << endl; // 1024 #12 } #13 /* #14 VC6 #15 error C2440: 'initializing' : cannot convert from 'const int *' to 'int *& ' #16 A reference that is not to 'const' cannot be bound to a non-lvalue #17 #18 BCB4 #19 Warning W8028 : Temporary used to initialize 'pi_ref' in function main() #20 Error E2034 : Cannot convert 'const int *' to 'int *' in function main() #21 #22 G++ #23 warning: converting to `int *' from `const int *' discards const #24 warning: initializing non-const `int *&' with `const int *' will use a temporary #25 */ #26 #27 #28 { // 情況 2 #29 const int *&pi_ref = &ival; // 書上說這不可以. vc6[x] cb4[o] g++[o] #30 cout << pi_ref << endl; // 0x0065FE00 0x259fc90 #31 cout << *pi_ref << endl; // 1024 1024 #32 } #33 /* #34 VC6 #35 error C2440: 'initializing' : cannot convert from 'const int *' to 'const int *& ' #36 A reference that is not to 'const' cannot be bound to a non-lvalue #37 #38 BCB4 #39 Warning W8028 : Temporary used to initialize 'pi_ref' in function main() #40 #41 G++ #42 warning: initialization of non-const reference `const int *&' from rvalue `const int *' #43 */ #44 #45 #46 { // 情況 3 #47 int *const &pi_ref = &ival; // 書上說這可以. vc6[x] cb4[x] g++[o] #48 cout << pi_ref << endl; // 0x259fc90 #49 cout << *pi_ref << endl; // 1024 #50 } #51 /* #52 VC6 #53 error C2440: 'initializing' : cannot convert from 'const int *' to 'int *const & ' #54 Reason: cannot convert from 'const int *' to 'int *const ' #55 Conversion loses qualifiers #56 #57 BCB4 #58 Warning W8028 : Temporary used to initialize 'pi_ref' in function main() #59 Error E2034 : Cannot convert 'const int *' to 'int *' in function main() #60 #61 G++ #62 warning: converting to `int *' from `const int *' discards const #63 */ #64 #65 { // 情況 4 #66 const int *const &pi_ref = &ival; // 我的看法 vc6[o] cb4[o] g++[o] #67 cout << pi_ref << endl; // 0064FDF4 0065FE00 0x259fc90 #68 cout << *pi_ref << endl; // 1024 1024 1024 #69 } #70 /* #71 VC6 #72 no warning, no error #73 #74 BCB4 #75 Warning W8028 : Temporary used to initialize 'pi_ref' in funcion main() #76 #77 G++ #78 no warning, no error #79 */ #80 #81 } 看來各家編譯器對 constness 的解釋與作法上的嚴謹程度多有不同。 看到你對書中文字的見解,我決定重新把原文找出來,看看有否 誤譯。再三斟酌後,我修改如下: ■p108, L10 原文: If we read this definition from right to left, we discover that pi_ref is a reference to a pointer to an object of type int defined to be const. Our reference isn't to a constant but rather to a nonconstant pointer that addresses a constant object. 原譯: 如果由右往左閱讀上述定義,我們會發現,pi_ref 是個 reference, 代表一個指標,此指標指向一個型別為 int 的 const object。 但是我們的 reference 實際上卻未被用來代表一個常數,而是被用來 代表一個非常數指標(該指標指向一個常數 object)。 更正: 如果由右往左閱讀上述定義,我們會發現,pi_ref 是個 reference, 代表一個指標,此指標指向一個型別為 int 的 const object。 我們的 reference 代表的不是一個常數指標,而是一個非常數指標, 指向一個常數 object。 不過直使修改為這樣,這段文字仍然不能給讀者很直覺的意義。 要在這裡將整個 constness 的精神說清楚,我實是也力有未逮。 建議你再全盤思索一遍,甚至包括 const member function。 至於你的第二個問題。是的,VC6 支援 default template parameters。 你的程式應該這麼寫: #include <vector> #include <string> using namespace std; void main() { // 表示不用 default template parameters vector<string, allocator<string> > svec; } 或是: #include <vector> #include <string> using namespace std; void main() { // 表示使用 default template parameters vector<string> svec; } 《C++ Primer》全書對於 container's default template parameters 的用法,都寫得不標準。可能因為作者 Lippman 使用早期的編譯器 或怎麼地 (who knowns, and who care!) 使用 STL,動不動就會來一堆令人畏懼的 error msg 或 warning msg。 所以,把根本觀念搞懂,至為重要,因為目前能輔助除錯或追蹤 STL 的 工具並不多(誰有這方面的使用經驗,請提供,謝謝) -- the end  -- ※ Origin: 楓橋驛站<bbs.cs.nthu.edu.tw> ◆ Mail: jjhou@ccca.nctu.edu.tw
文章代碼(AID): #ujF1C00 (CompBook)
文章代碼(AID): #ujF1C00 (CompBook)