看板CompBook
標 題C++ Primer 答客問 (37) - reference, allocator
發信站清華資訊(楓橋驛站) (Thu Feb 24 16:39:40 2000)
轉信站Ptt!bbs.ee.ntu!freebsd.ntu!news.cs.nthu!maple
C++ Primer 答客問 (37) - reference, allocator
侯捷
[email protected]
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: [email protected]