2017-07-20 7 views
0

私はC++でuniの研究を続けていますが、ポインタ、const引数、およびクラス実装の非常に基本的な点に関するいくつかの深刻な理解の問題に取り組んでいます。 C++)関数内のC++ const引数

私は通常Javaで動作するので、C++は非常に新しくなっています。

これは、クラスのための私の単純なヘッダ「人」である:

#ifndef Person_h 
#define Person_h 

class Person 
{ 
private: 
    char* name; 
    char* adress; 
    char* phone; 

public: 
    Person(); 
    Person(char const *name, char const *adress, char const *phone); 
    Person(const Person &other); 
    ~Person(); 

    void setName(char const *name); 
    char* getName() const; 
    void setAdress(char const *adress); 
    char* getAdress() const; 
    void setPhone(char const *phone); 
    char* getPhone() const; 
}; 

#endif // !Person_h 

そしてここで問題が開始されます。実際のchar変数の代わりにcharポインタを使用するのはなぜですか?メモリを節約したり、パフォーマンスを向上させるための規則がいくつかありますか?

これが私たちの教授コードの方法であると私たちは、ポインタを使用することを理解させるためにしようとconstなど

今ここにクラスの私の実装です:

#include "Person.h" 
//Person.h class implementation 

Person::Person() 
{ 
    Person::name = new (char[64]); 
    Person::adress = new (char[64]); 
    Person::phone = new (char[64]); 
} 

Person::Person(const char *name, const char *adress , const char *phone) 
{ 
    Person::name = new (char[64]); 
    Person::adress = new (char[64]); 
    Person::phone = new (char[64]); 

    setName(name); 
    setAdress(adress); 
    setPhone(phone); 
}; 

Person::Person(Person const &other) 
{ 
    Person::name = new (char[64]); 
    Person::adress = new (char[64]); 
    Person::phone = new (char[64]); 

    setName(other.getName); 
    setAdress(other.getAdress); 
    setPhone(other.getPhone); 
}; 

Person::~Person() 
{ 
    delete [] name; 
    delete [] adress; 
    delete [] phone; 
}; 

void Person::setName(const char *name) 
{ 
    this->name = name; 
}; 

char* Person::getName() const 
{ 
    return name; 
}; 

void Person::setAdress(char const *adress) 
{ 
    this->adress = adress; 
}; 

char* Person::getAdress() const 
{ 
    return adress; 
}; 

void Person::setPhone(char const *phone) 
{ 
    this->phone = phone; 
}; 

char* Person::getPhone() const 
{ 
    return phone; 
}; 

我々は手動で割り当てることを学ぶ必要がありますメモリを要素に割り当て、全体的なメモリ管理に注意してください。したがって、setter関数のconst引数の使用。私は要素の議論を変えないためにこれがあると思いますか?私は非常に困惑している、基本的には...

そして、私のIDE(MS VisualStudioを2015年)は、エラーとして次の行を強調:

void Person::setName(const char *name) 
{ 
    this->name = name; //error 
}; 

「型の値 'のconstのchar *が' に割り当てることはできません'char *'型のエンティティ

これらの値を割り当てることができない場合、なぜconstを使用する必要がありますか?または、メンバー変数自身を変更せずに、それらをどのように "un const"することができますか?const

この全体の問題は今私にとって大きな混乱の1つに過ぎません。

EDIT:I 私の試験にC-文字列を使用するのは、私たちの教授を参照するポインタとメモリ管理を理解するためです。

+2

>実際のchar変数の代わりにcharポインタを使用するのはなぜですか? < あなたは、それのための 'std :: string'があります。 – myaut

+2

裸のポインタではなく、文字列データを保持するために 'std :: string'を使うべきです。あなたに良いC++の本が必要なように私に見えます。 – Bathsheba

+2

Cスタイルの文字列を割り当てるときは、文字列値をコピーするのに '='ではなく 'strcpy'を使います。 –

答えて

2

this->name = name; 

は、2つの理由のために問題がある:あなたのためにすべてが密接に関連しているが、まだ別の型の変数に1型の変数を代入しようとするまず。しかし、それは大きな問題ではありません。

大きな問題がに(どこか別のポイント)ポインタで(あなたが割り当てられているいくつかのメモリを指す)、元のポインタthis->nameを再割り当てあなたはにしようということです。

結果は

int a = 5; 
int b = 10; 
a = b; 

に類似しており、次いでaがもはや5に等しい理由を疑問に思っていません。

ここには2つの解決策があります:最初のポインタはポインタを使用し続け、次にポインタを割り当てる代わりにをコピーします。これはstd::strcpy関数で行われます。

私が推奨する解決策は、文字列のポインタの使用をやめ、代わりに標準のC++ std::stringクラスを使用することです。次に、を使用して文字列をコピーする単純な割り当てを使用します。彼らはまた、独自のメモリを処理するので、メモリリーク、ポインタ、無効なポインタを解放するか、文字列の実際のサイズを把握する必要はありません。

std::string C++のクラスは、Java Stringクラスといくつかの類似点を共有しています。したがって、Javaのバックグラウンドから来た場合、調整するのは難しくありません。最大の違いは、C++ではstd::stringを使用しています。実際には==と直接比較できます。

+0

わかりやすく理解するために私の試験にC-文字列を使用する必要があります。そのため、私たちは標準のC++文字列を使用しませんが、説明のおかげで、今はポインタ割り当てに本当の問題があります。 – GenerationLost

1

現代のC++ではメモリ管理についてはまだ認識しているはずですが、読みやすさ、例外の安全性およびバグのために、std :: stringのような作業を行うコンテナを使用するべきです。

のconstのchar *の名前は、それ自体が、このメモリ部内のデータは変更されないことを、意味のconst、あるメモリ部、を指すポインタを、持っていること、を意味します。

ポインタ自体が変更される可能性があります。

あなたは名前だけのポインタへのポインタthis->名を割り当てる

this->name = name; 

を割り当てます。しかし、これは、ポインタがコンバーチブルタイプの場合にのみ実行できます。 this-> nameの型をchar *からconst char *に変更すると、コンパイラは不平を言ってはいけません。

新しいものを割り当てる前に、メモリをクリーンアップする必要があります。 nameがCONSTで、this->nameは非constであるとき、あなたの関数がnameの内容が読み取りとして扱われることを約束しているので、素人の面では、[] this->名前

+0

私の試験では、Cスタイルの文字列を使用する必要がありますが、説明とメモリのクリーンアップのヒントに感謝します! – GenerationLost

1

を削除し、this->name = name;が動作しない理由は、ありますこのポインタを非constポインタに代入することで、自由にデータを修正して、あなたの約束を破ることができます。

あなたの先生は明らかに古いスタイルのC++にポインタ(本質的にはオブジェクト指向のC)を教えているので、ではなく、に進み、文字ポインタで文字ポインタを置き換えてください。もしあなたがそうすればあなたの先生はおそらく不幸になるでしょう。

我々はchar*代わりのchar[]を使用する多くの理由があります。

  • 一つの理由は効率である:そのchar[]char[]全内容を渡すためにスタックにコピーされる必要があるであろう。 char*を渡すと、1つの機械語だけがコピーされます。

  • もう一つの理由は、それが実際には不可能であるということです。コンパイラには、char[]がゼロ終端されているため、a)十分なスタック領域を確保し、b)スタックにコピーするための知識が組み込まれていません。言語の作成者は、そのようなビルトインの知識を言語に入れないことを好みました。代わりに、char[]を暗黙的にchar*に変換する必要があります。そのため、関数内からchar*として受け取って、必要な処理を行うことができます。

  • もう一つの理由は、あなたのchar[]がちょうど少し大きすぎた場合、その後、あなたのスタックがオーバーフローするということです。我々はマシンの言葉よりも大きな(またはかなり大きい)ある型の値を渡したいとき

だから、すべてのこれらの理由のために、我々は値そのものを渡すことはありません、我々は彼らへのポインタや参照を渡します。

+0

配列のコピーをC++で渡すことはできません。 'char []'は暗黙的に 'char *'に変換されます。配列を渡すようなものはありません(デフォルトでは値がコピーされます) – KostasRim

+1

@KostasRimはい、実際には「別の理由は実際には不可能です...」 –

+0

小さな編集をしてください私はupvoteすることができます。 – KostasRim

関連する問題