看板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]