C++開發的項目難免會用到STL的string,使用管理都比char數組(指針)方便的多,但在得心應手的使用過程中也要警惕幾個小陷阱,避免我們項目出bug卻遲遲找不到原因。
#include <iostream> #include <string> #include <stdlib.h> using namespace std; struct flowRecord { string app_name; struct flowRecord *next; }; int main() { flowRecord *fr = (flowRecord*)malloc(sizeof(flowRecord)); fr->app_name = "hello"; out << fr->app_name << endl; return 0; }
嗯,當然不是簡單的輸出 “hello”了,在Linux下用g++編譯后運行試試,會出現“Segmentation fault (core dumped)”,why?問題就出在給fr指針分配內存的時候,注意這里用的是C中的malloc而不是new,如果你換成new再運行,就不會報錯 了,成功的輸出“hello”,那為什么malloc就不行呢?這就要看 malloc()與new()的區別了,關於兩者的區別是程序員面試中屢問不爽的經典面試題,所以相信一般的程序員都知道它們之間有一個非常重要的區別就是: new在分配內存時會調用默認的構造函數,而malloc不會調用。 而STL的string在賦值之前需要調用默認的構造函數以初始化string后才能使用,如賦值、打印等操作,如果使用malloc分配內存,就不會調 用string默認的構造函數來初始化結構體中的app_name字符串,因此這里給其直接賦值是錯誤的,應該使用new操作符。這也 提示我們用C++開發程序時,就盡量使用C++中的函數,不要C++與C混合編程,導致使用混淆,比如有時候new分配的內存卻用free釋放。
2. c_str()函數問題
c_str()函數用於string與const char*之間的轉換,也經常能用到,下面的例子你說輸出啥?
#include <iostream> #include <string> using namespace std; int main() { string s = "Alexia"; const char *str = s.c_str(); cout << str << endl; s[1] = 'm'; cout << str << endl; return 0; }
嗯,第一個不用多說,第二個輸出是“Alexia”還是“Amexia”呢?答案是后者,咋一看const char*的值應該是個常量啊,怎么還能改變值呢?哈,又是個經典的面試題:
const char*, char const*, char* const的區別是什么?老生常談的問題,const char*與char const*是等價的,指的是指向字符常量的指針,即指針可以改變指向但其指向的內容不可以改變,而char* const相反,指的是常量指針,即指向不可以改變但指針指向的內容可以改變。因此這里的const char*指向的內容本類是不可以改變的,那么這里為什么改變了呢?這跟str這個const char*的生命周期及string類的實現有關,
string的c_str()返回的指針是由string管理的,因此它的生命期是string對象的生命期,而string類的實現實際上封裝着一個char*的指針,而c_str()直接返回該指針的引用,因此string對象的改變會直接影響已經執行過的c_str()返回的指針引用。
3. 字符串字面值與標准庫string不是同一種類型
直接看下面的例子:
string s("hello"); cout<<s.size()<<endl; //OK cout<<"hello".size()<<endl; //ERROR cout<<s+"world"<<endl; //OK cout<<"hello"+"world"<<endl; //ERROR
可以看出兩者是非常不同的,不能混淆使用。