[英]C++ char * pointer passing to a function and deleting
我有以下代碼:
#include <iostream>
using namespace std;
void func(char * aString)
{
char * tmpStr= new char[100];
cin.getline(tmpStr,100);
delete [] aString;
aString = tmpStr;
}
int main()
{
char * str= new char[100];
cin.getline(str,100);
cout<< str <<endl;
func(str);
cout<< str <<endl;
return 0;
}
為什么第二個cout
不打印第二個輸入字符串? 如何更改此代碼才能使用它?
正如GregS所說,簡單的答案是使用引用聲明你的函數:
void func(char *&aString)
然而,它並不是真正的最佳解決方案。 在C ++中,您通常避免使用簡單數組並使用容器。
#include <iostream>
#include <string>
void func(std::string &s)
{
std::getline(std::cin, s);
}
int main()
{
std::string str;
func(str);
std::cout << str << std::endl;
return 0;
}
因為第二個cout
將打印str
指向的內容。 並且,主函數中的str
,在調用func
之前和之后將具有相同的值。
實際上,在func
函數中,您正在更改aString
變量的值。 但這是主要的另一個變量而不是str
。
如果希望更改str
的值,則必須通過引用或指針將其傳遞給func
。 (注意你寫的是通過指針傳遞字符。我的意思是你必須通過指針傳遞指針: void func(char **str_ptr)
,或者通過引用void func(char *&str_ref)
)
如果你真的在做C ++,你應該使用std :: string而不是舊的C字符串。
通過指針傳遞指針的示例:
func(char ** aString)
{
char * tmpStr= new char[100];
cin.getline(tmpStr,100);
delete [] *aString;
*aString = tmpStr;
}
另外你應該這樣稱呼: func(&str);
當從main()調用func()時,str指針的值被傳遞給函數(這是通過將它的值復制到堆棧來完成的)
調用func()時存儲在堆棧上的值成為func()中的局部變量aString。 您可以修改此值,但只要func()返回它的所有局部變量就會被丟棄。 aString的值不會被復制回str 。
要使代碼工作,您必須:
將func更改為
void func(char * aString)
{
cin.getline(aString,100);
}
它起作用,至少它對我有用。
如果您的目標是實際從鍵盤讀取一行,請執行以下操作:
std::string foo;
std::getline(std::cin, foo);
否則,當您將指針傳遞給函數時,指針將按值傳遞 。 這意味着您無法在函數內更改指針本身,但您可以更改它指向的對象。 在C ++中,您可以按如下方式執行此操作:
void bar(std::string & s) {
std::getline(std::cin, s);
}
// in calling code
std::string foo;
bar(foo);
這會將對字符串的引用傳遞給函數。 該函數現在可以更改字符串的內容。
如果要編寫一個分配一些內存來存儲結果的函數,請執行以下操作:
boost::shared_array<char> foo() {
boost::shared_array<char> result(new char[100]);
std::cin.getline(result.get(), 100);
return result;
}
指針按值傳遞。 是的,您可以更改指針指向的內容 ,但退出函數時會保留舊地址本身。 因此,“aString = tmpStr”; 變得無用,“char * tmpStr = new char [100];” 造成內存泄漏。 您需要通過引用傳遞指針:
void func(char*& aString)
{
char * tmpStr= new char[100];
cin.getline(tmpStr,100);
delete [] aString;
aString = tmpStr;
}
賦值給函數中的參數aString對main()中的str沒有影響
你可能會試試
return aString
在主要的
str = funct(str);
但事實上,沒有理由將str傳遞給函數。
行aString = tmpStr
只是將astring
(即地址/指針)的值更改為另一個值(即另一個地址/指針),而不是aString
指向的內容。
您可以嘗試將簽名更改為:
void func(char ** aString)
並將最后兩行func
更改為:
delete [] *aString;
*aString = tmpStr;
因此,最后一行導致程序將存儲在aString
指向的內存中的地址更改為新分配的地址( tmpStr
)。 (我知道,這是令人難以置信的。)
然后通過它來調用它
func(&str);
您需要傳遞str作為參考。
#include <iostream>
void func(std::istream& is, std::string& aString)
{
std::getline(is, aString);
}
int main()
{
std::string str;
std::getline(std::cin, str);
if(std::cin)
std::cout<< str << '\n';
std::string str;
func(std::cin, str);
if(std::cin)
std::cout<< str << '\n';
return 0;
}
傳遞給func()的指針aString
表示可以讀取和寫入字符串str
位置(在哪個地址)。 當你說aString = tempStr
,你將用一個新值( tempStr
指向的字符串的地址)替換它的原始值( str
指向的字符串的地址)。 這不會導致str
指向與tempStr
相同的位置。
想象一下,我和朋友的家庭住址給你一張紙。 然后你把它刮掉並寫上你兄弟(住在倫敦)的地址。 如果我決定去拜訪我的朋友,我將不會發現自己前往倫敦,即使你可能有一張紙上寫着“保羅的朋友:123倫敦”。
要讓main
打印出你在func
()中輸入的字符串,你可以將輸入字符串復制到aString(你將你的兄弟移動到我朋友家),或者將指針或引用傳遞給str(讓我給你我的地址)預訂,所以你可以把我的朋友的條目改為倫敦)。 無論哪種方式,下次我訪問“我朋友的家”時,你的兄弟都會在那里。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.