1. 程式人生 > >C++ string中的幾個小陷阱,你掉進過嗎?

C++ string中的幾個小陷阱,你掉進過嗎?

stl 試題 賦值 clu ror ati world mod iostream

C++開發的項目難免會用到STL的string。使用管理都比char數組(指針)方便的多。但在得心應手的使用過程中也要警惕幾個小陷阱。避免我們項目出bug卻遲遲找不到原因。


1. 結構體中的string賦值問題

直接通過一個樣例說明,以下的樣例會輸出什麽:
#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";
    cout << 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

能夠看出兩者是很不同的。不能混淆使用。





C++ string中的幾個小陷阱,你掉進過嗎?