#include <iostream>
using namespace std;
class Marks
{
public:
char* name();
};
char* Marks::name()
{
char temp[30];
cout<<"Enter a name:"<<endl;
cin.getline(temp,30);
return temp;
}
int main()
{
char *name;
Marks test1;
name=test1.name();
//cout<<"name:"; //uncomment this line to see the problem
cout<<name<<endl;
return 0;
}
答えて
問題は、名前が指している値が破棄されたためです。ローカル変数のアドレスをMarks::name()
から戻しています。最初のcout
の副作用の可能性が最も高いため、name
の内容が破壊されています。最初のcout
がコメントアウトされていると、あなたはたぶん幸運になるでしょう。
char* Marks::name()
{
char* temp = new char[30];
cout<<"Enter a name:"<<endl;
cin.getline(temp,30);
return temp;
}
int main()
{
char *name;
Marks test1;
name=test1.name();
cout<<"name:";
cout<<name<<endl;
delete[] name;
return 0;
}
いうだけでdelete
よりも、delete[]
を使用することを忘れないでください、以来:あなたが完了したら
これを行うための正しい方法は、いくつかのメモリを割り当てることを返却し、それを破壊することですそれ以外の場合、最初の文字のみが割り当て解除されます。
メモは、呼び出し先が割り当てて呼び出し元が処理することに注意してください - これは悪い設計であり、メモリリークの潜在的な原因です。呼び出し元と呼び出し先が別々のライブラリに含まれると考えてください。 – dirkgently
それは良い点です。私はちょうどポイントを得るためにコードサンプルを小さく保つことを試みていた。 – Andy
Marks::name()
メソッドが終了するたびに解放されるスタックベースのポインタ(呼び出されたプロセスのスタックにあるポインタ)を返します。
これは基本的なC/C++メモリ管理に関する質問ですので、このトピックに関するいくつかの書籍を読むことをお勧めします。
これを正しく行うにはいくつかの方法があります。例えば、呼出関数に文字列のメモリを確保し、機能にこのポインタを渡す:main()
方法において
:
char name[30];
Marks test1;
test1.name(name);
対応する方法を用いて(ここでname
が正しい値を有します)。
char* Marks::name(char* temp)
{
cout<<"Enter a name:"<<endl;
cin.getline(temp,30);
return temp;
}
しかし、文字列の静的および動的メモリを管理する他の方法があります。
まあ、一時変数へのポインタを返すMarks :: name()にはかなり厄介なバグがあります。 tempはスコープの外に出て行くので関数の終了時に破棄されるので、もはや存在しない変数へのポインタを返しています。
ローカル変数のアドレスを返却されています
char temp[30];
// ...
return temp;
これは、厳密なノーノーCまたはC++です。あなたがMarks::name()
から出てくる瞬間に、あなたのtemp
変数がブームになります!あなたはもはやそれにアクセスすることができません - それは未定義の動作を呼び出します。これを試してみてください
#include <string> // somewhere at the top
// ...
std::string Marks::name()
{
std::string line;
cout<<"Enter a name:"<<endl;
std::getline(cout, line);
return line;
}
文字列が常に利用できるとは限りません。時には、ちょうどchar *の下に落ちて汚れていなければなりません。 – xan
例を挙げることができますか? IMHO、getline()とcharバッファで入力を管理するのは、最も簡単な作業ではありません。 – dirkgently
1つのためのゲームプログラミング。しばしばそうではありませんが、その種のアプリケーションでは、stdやboostライブラリの一部を利用できないかもしれません。私はこの正確な問題を具体的には意味しませんでしたが、私はmemと同様の問題に直面しました。内部関数を自分で割り当てます。 – xan
これまでの回答はすべて正しいものですが、これを実装する方法のいくつかは改善されている可能性があります。私はその非常に簡単なテストアプリケーションを知っているが、次の点を考慮してください
ここchar* Marks::name()
{
char* temp = new char[30];
cout<<"Enter a name:"<<endl;
cin.getline(temp,30);
return temp;
}
int main()
{
char *name;
Marks test1;
name=test1.name();
cout<<"name:";
cout<<name<<endl;
delete[] name;
return 0;
}
、それはメモリを割り当てている関数名()であるが、それはそれを削除されていません。これは、特に複雑なシナリオでは、問題につながる矛盾です。これをやるほうがいいかもしれません(あなたには人がどのくらいのスペースを書き込むかを事前に知っていると仮定します...)
//this time, pass in some ALREADY allocated memory, and a length count.
void Marks::name(char *buf, int len)
{
cout<<"Enter a name (max " << len <<" letters):"<<endl;
cin.getline(buf,len); //read into the memory provided
}
int main()
{
//preallocate your memory so that the same code that allocates...
char *name = new char[30];
Marks test1;
test1.name(name, 30);
cout<<"name:";
cout<<name<<endl;
//... also deallocates it. This is perhaps cleaner in terms of responcibility.
delete[] name;
return 0;
}
実際には、この種のことを行う正しい方法と間違った方法はありません。場合によっては、関数が使用するメモリを割り当てる必要があります。これは、他のアプリケーションで使用するためにこれを返す必要があります。これは、誰が新しくなったのかを考え、削除するときに一貫性を持たせようとする例です。
Marks :: name()は、ローカル変数へのポインタを返します。 関数が終了すると、そのメモリは解放されます。
Marks :: nameとcout :: operatorの呼び出しの間に関数を呼び出さない限り、まだ適切な出力が得られる理由は、< <です。
静的でない文字列を値で返す場合は、char *の代わりにstd :: stringを使用できます。
また、あなたは* charとして名前の関数にchar型のバッファを渡すと、バッファのサイズを渡し、マーク::名前が(strncpyをまたはstrncpy_sを使用して例えば)そのバッファを満たす可能性があり
void Marks::name(char* buffer, int length)
{
cout<<"Enter a name:"<<endl;
cin.getline(buffer,length);
}
void main()
{
char buffer[30];
Marks::name(buffer, 30);
}
+1 - それは私が運転していたもので、コンパイル時にバッファの大きさを知っている限り、スタックに割り当てる方がはるかに優れています。 – xan
- 1. std :: coutが出力に改行または改行を追加するのはなぜですか?
- 2. なぜ出力が表示されないのですか?
- 3. JupyterノートブックにC++出力(cout)が表示されない
- 4. テキストテキストのプロパティに変数の内容が表示されない
- 5. httpリクエストに変数の内容が表示されない - jmeter
- 6. PyQt4:QStandardItemに変数の内容が表示されない
- 7. Emacsにシェルの出力が表示されないのはなぜですか?
- 8. 合成時に出力が表示されないのはなぜですか?
- 9. コードビハインドで追加したDataGridで、DataGridに新しい列が表示されないのはなぜですか?
- 10. VS2010 oracleクエリーウィンドウで出力が表示されないのはなぜですか?
- 11. PowerBIで出力データセットが表示されないのはなぜですか?
- 12. なぜPythonスクリプトを実行した後に端末に出力が表示されないのですか?
- 13. "cout << cout"がアドレスを出力するのはなぜですか?
- 14. PHP変数の内容が表示されない
- 15. なぜ私の出力がすぐに表示されないのですか?
- 16. 動的に追加されたListViewがLinearLayoutに正しく表示されないのはなぜですか?
- 17. JTextAreaへのリアルタイム出力が表示されないのはなぜですか?
- 18. なぜ、Coutは「ナノ」出力を出すのですか?
- 19. ズームコントロールを追加しても表示されないのはなぜですか?
- 20. jQueryセレクタに新しく追加された要素が表示されないのはなぜですか?
- 21. appendAttributedStringが新しい行に追加された文字列を表示するのはなぜですか?
- 22. キュウリの背景からの出力が1回だけ表示されるのはなぜですか?
- 23. Makefile:コンパイル出力が表示されないのはなぜですか?
- 24. 動的に追加されたjQuery-uiタブの内容は1回だけ表示されます
- 25. なぜプログラムに出力が表示されないのですか?
- 26. なぜチャートに追加ポイントが表示されないのですか?
- 27. htmlでクラス名を追加した後に画像が表示されないのはなぜですか?
- 28. Junoのワークスペースに変数が表示されないのはなぜですか?
- 29. なぜ2つのdivの出力が表示されないのですか?
- 30. バイナリファイルの内容が表示されるのはなぜですか?
それは可能性があります期待される出力と実際の出力を質問の一部として入力すると便利です。 –
サンプル出力はどうですか?予想される実際の行動? (あなたのコードをインデントするのもいいでしょう:-P) –
次の質問のために上記の質問を含める: –