第一種情況:(錯誤)
#include <vector>
using std::vector;
#include <string>
using std::string;
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
int main()
{
vector<string*> spvec;
string str;
while (cin>>str)
{
string *pstr;
pstr=&str; //這樣結果每次pstr都指向str.隨著str的輸入
//再者pstr是臨時變數,遇"}",被銷毀,隨著str被
//改寫,最後結果一樣都是最後一個str;
spvec.push_back(pstr);
}
for (vector<string*>::iterator iter=spvec.begin();iter!=spvec.end();++iter)
{
cout<<**iter<<" ";
}
getchar();
return 0;
}
如上程式,運行後,假設輸入 adfdsfds fdsfds dfdf fd fd df dffd df d sfd fas
運行結果: fas fas fas fas fas fas fas fas fas fas fas
分析while迴圈:
1.建立臨時變數*pstr,其指向str串,即("adfdsfds"),然後將此指標放到spvec[0]中, 此時,當遇到"}"時,pstr生存期結束,即釋放,spvec[0]-->str,str的生存期是直到main的"}"才結束。
2.建立新的臨時變數*pstr,其指向str串,即("fdsfds "),然後將此指標放到spvec[1]中, 此時,當遇到"}"時,pstr生存期結束,即釋放,spvec[1]-->str("fdsfds"),而此時spvec[0]指向的str值已經更改,所以*spvec[1]="fdsfds ";
......
如此一直下去,結果導致*spvec[n]即**iter均為最後一個str.
上面的 pstr臨時變數是在棧上建立的,他的生存期就是他所處的語句塊(也就是離他最近的一對{})。
第二種情況: (正確)
先寫一個模型
spvec string str
iter --> spvec[0](pstr[0]) --> str
spvec[1](pstr[1]) --> str
spvec[2](pstr[2]) --> str
spvec[3](pstr[3]) --> str
spvec[4](pstr[4]) --> str
spvec[5](pstr[5]) --> str
spvec[6](pstr[6]) --> str
接下來把
string *pstr=&str; 改為 string *pstr=new string;
*pstr=str;
spvec.push_back(pstr);
運行結果: adfdsfds fdsfds dfdf fd fd df dffd df d sfd fas //正常
分析while迴圈:
1.在堆上建立變數*pstr,然後*pstr=str,把str的內容直接複製到pstr指向的空間,此空間遇到"}"時,生存期沒結束,結果即spvec[0]=pstr[0]
2.在堆上建立另一變數*pstr,然後*pstr=str,把str的內容直接複製到pstr指向的空間,此空間遇到"}"時,生存期沒結束,結果即spvec[1]=pstr[1]
.....
如此一直下去,結果導致每個spvec都儲存一個指標。
上面的 pstr臨時變數是在棧上建立的,棧它是由作業系統管理的,我們自己建立一定得 自己釋放,不然會造成記憶體垃圾
第三種情況:(錯誤)
string *pstr; //不可沒用new。不用的話,此指標指向空間未知
//(也不可以=0,0隻是初始化其無指向任何對象)
*pstr=str; //後直接 用str 對此指標空間的內容賦值,會出現異常
spvec.push_back(pstr);
第四種情況:(錯誤)
string *pstr=new string; //跟第一種情況差不多。雖然有在堆上分配空間
pstr=&str; //每次pstr都是取str的地址,結果導致每個*spvec[n]
//的string均為最後一個
spvec.push_back(pstr);