正文

std:string、char *和char []的问题2008-06-11 12:24:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/vfdff/36018.html

分享到:

string str_s = "abc";
char *str_cp = "abc";
char str_ca[] = "abc";

1. str_cp是指针,指向一段数据有四个元素,分别是'a', 'b', 'c', '\0'。

2. str_ca是数组,它包含四个元素,分别是'a', 'b', 'c', '\0'。

引用
我知道*str_cp的"abc"多了一个'/0'

这个说法不正确。数组str_ca也会有'\0'。但如果你写char str_ca[] = {'a', 'b', 'c'}则不会有'\0'。

3. 
引用
str_ca相当于一个char * const str_cp

这个说法不正确。数组和指针是不同的,数组不能看作常指针。证据就是:
char* const s = "abcdef";
char a[] = "abcdef";
则sizeof(s)一般为2或者4,而sizeof(a)为7。
指针只保存了所指向的地址,数组既包括首地址的信息,还包括长度的信息。不过数组在作为参数传递时,可以转化为指针的形式(数组首地址作为指针所指地址,数组长度信息被丢弃)。

4. 
引用
string str_s 本质上是什么呢?

从对象的观点看。str_s就是一个对象,其中包含了字符串数据,如此而已。至于对象内部是如何操作,以保证正确的包含这个字符串数据,这完全取决于string类的作者。这种现象体现了面向对象编程思想中的一个重要观点——封装。作为类的使用者,我们只要知道它应该怎么用即可,不需要知道它是如何工作的。也就是说不需要知道它的本质。
当然我们也不能一无所知。为了更好的使用这个类,它的基本特性要了然于心。比如,我们要知道string中的字符是连续存储的,而不是通过链表来进行存储的。等等。

5. 
引用
一般做开发都得转换成 char*的吗?

不是的。C++本身的输入输出就直接支持string。比如:
string s;
cin >> s;
cout << s;
虽然string是鼓励的,但这并不意味着char*就是应该被抛弃的。很多时候还是会用到char*。例如你从zip包中解压出一个文件,因为很多zip压缩解压的程序都用C语言写,因此文件解压得到的数据在内存中很可能就是以char*的形式存在的。

6. 
引用
我可以在一个函数里返回一个 数组名称/string变量/char *,然后给一个 char * /string/char[] 这样赋值行吗?

这个问题比较细,下面一点一点的分析。
(1) 返回一个char*,赋值给char*。可以。
(2) 返回一个char*,赋值给string。可以。运行时实际的情况是,根据char*的值构造一个临时的string对象,把这个临时的string对象赋值给你的string变量,最后销毁临时的string对象。
(3) 返回一个char*,赋值给char[]。不可以。char[]是数组,数组是不允许赋值的。只有数组的元素才能赋值。
(4) 返回一个string变量,赋值给char*。不可以。因为string不能转化为char*。你可以通过string类的c_str方法取得它的指针,但是要注意,如果string对象本身被销毁了,则指针所指的数据也跟着无效。例如:
string func() {
    return string("abc");
}
int main() {
    char* s = func().c_str();
    cout << s;                // 错误!!
}
因为函数func()返回后,它的返回值是临时的。通过c_str取得它的指针赋值给s后,临时值被销毁,因此s指向的是一个无效的位置。
(5) 返回一个string变量,赋值给string。可以。
(6) 返回一个string变量,赋值给char[]。不可以。char[]是数组,数组是不允许赋值的。只有数组的元素才能赋值。
(7) 如果返回数组的名字,其实是返回数组的首地址,也就是一个指针。所以这其实跟返回char*是非常类似的。唯一需要注意的问题是,如果数组是局部变量,并且不是static的,则函数返回时数组会被销毁,所以返回的指针所指向的位置也是无效的。例如:
char* func() {
    char a[] = {"abc"};
    return a;
}
int main() {
    char* s = func();
    cout << s;                // 错误!!
}

7. 
引用
我如果cout < <str_cp[1] 此时指向'b'如果以'\0'为结束标志的话,应该输出的是bc 啊

这个涉及到数据类型的问题。cout会根据数据的类型和数据的值来确定最终的输出。对于char类型,cout只输出一个字符,对于char*类型,cout输出多个字符,直到遇到'\0'才结束。
因为str_cp是char*类型,所以str_cp[1]是char类型。所以cout << str_cp[1]实际上是输出char类型,因此只输出一个字符。
但str_cp + 1是char*类型,所以cout << (str_cp+1)实际上是输出char*类型,因此输出多个字符,遇到'\0'才结束。
如果觉得(str_cp+1)不够直观,可以写为&str_cp[1]。(虽然后一种写法看起来执行了两步操作,但实际上两种写法编译后得到的代码是一样的,不会有效率问题)

阅读(12659) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册