- 黑桃云
-
(1) vector<string> words2(words, words + words_size); 这种初始化方式没有问题,vector调用了vector(_Iter _First, _Iter _Last)拷贝构造,源码为:
template<class _Iter>
vector(_Iter _First, _Iter _Last)
: _Mybase()
{ // construct from [_First, _Last)
_Construct(_First, _Last, _Iter_cat(_First));
}
从源代码分析可见参数是指针类型适配的,即能够正确转换指针类型。也就是说在我的编译环境下(visual studio 2008)并没有出现任何编译错误,程序运行完全正确。
(2)关于char* p[]={"ads","tpy"...};这的确是定义了指向字符串指针的指针。这个问题分解为两个层次(二维)比较好懂些。
先看第一维,这个维度很好理解,就是可以有任意个元素(每个元素是一个字符串的指针),一旦这个“任意个数”确定下来,那么这一维就定下来了,不会改变。比如我就写填了2个字符串,char* p[]={"ads","tpy"};那么运行期第一维就是2,不会变了。
即:(按指针解引用*)
cout << *p << endl; // 输出ads
cout << *(p + 1) << endl; // 输出tpy
当然你知道下面的写法是等价的:(按元素)
cout << p[0] << endl; // 输出ads
cout << p[1] << endl; // 输出tpy
难理解一点的是第二维,即字符串指针所指字符串的长度,是随着每个元素变化的。想一想,你要定义一个可变长度的字符串数组是怎么定义的?是不是这样啊:
char str1[] = {"a", "d", "s"}; // p[0]的化身
char str2[] = {"t", "p", "y"}; // p[1]的化身
当然实际中并没有str1和str2这个中间变量,你不妨想象它们的确存在。我们当然确信字符串指针p[0]所指的地址和*p完全一样,p[1]所指的地址和*(p + 1)完全一样,那么我们有理由认为cout << *p[0]应该输出"ads", cout << *p[1]应该输出"tpy",非也!把中间变量拿进去做一下替换看看吧:
cout << *p[0]; <==> cout << *str1; // 这难道不该输出"a"么?
同理,cout << *p[1]; <==> cout << *str2; // 这难道不该输出"t"么?
举一反三,
cout << *(p[0] + 1); <==> cout << *(str1 + 1); // 当然应该输出"d"!
cout << *(p[0] + 2); <==> cout << *(str1 + 2); // 当然应该输出"s"!
cout << *p[0]; <==> cout << *(*p); //这样子才是等价的哦
原来秘密在这里:编译器对解引用*进行运算时,是类型敏感的!
再一次深入浅出:在我们取到第一维时,类型为char*, 解引用运算就是在第一维上,*p为第一个字符串,当然*(p + 1)就取到下一个字符串了;当我们取到其元素p[0]了,再进行解引用,这是已经到第二维了,编译器看到的类型为char,则必然*p[0]为第一个字符串首字符"a",*(p[0]+1)第一个字符串第二个字符!
问题看似很简单,实则并非表面那么简单。记住,我们写的程序是编译器转换为机器语言的,而非我们大脑的想象。
- 苏萦
-
这是字符指针数组,char* words[] = {"stately", "plump", "buck", "mulligan"}可以理解为
string str[] = {"stately", "plump", "buck", "mulligan"}
- okok云
-
char* p[]={"ads","tpy"...}
等于定义了一个指针数组。即指向指针的指针。所以这里*p跟p[0]一样,都是指向字符串"ads"的指针。。
- Chen
-
5特法