2

メッセージクラスの現在の実装を次のように変更します。

class Message
{
public:
    Message(uint8* buffer, uint8 length) : m_contents(buffer), m_length(length) { }

    uint8 getLength() const {return m_length; }
    const uint8* getData() const { return m_contents; }
protected:
    uint8* m_contents;
    uint8 m_length;
};

コンストラクターで長さのみを取得し、コンストラクターで動的に割り当て、デストラクタで削除します。

私はそれが次のように見えるべきだと思います:

Message(uint8 length) : m_length(length)
{
    m_contents = new uint8[length];
}

~Message() 
{
    delete [] m_contents;
    m_contents = NULL;
}

追加情報:メッセージオブジェクトはシリアルポートオブジェクトに渡され、シリアルポートオブジェクトが送信します。また、複数のCustomMessageクラスにサブクラス化されます。

私の質問は次のとおりです。この簡単な例では、ある種のスマートポインタを使用する理由はありますか?例が役立ちます。ありがとう!

4

2 に答える 2

2

ある種のスマートポインタを使用する理由はありますか?

実際には状況によって異なります。このコードを考えてみましょう:

 Message m1 (1024);
 Message m2 (m1);

あなたm2 はの深いコピーになりたいm1ですか?の基になるバッファとm1メモリm2を共有しますか?または、コピーを(深いまたはその他の方法で)始めたくないですか?つまり、2番目のステートメントはコンパイルエラーになりますか?

  • それらにメモリを共有させたい場合は、はい、を使用する必要がありますstd::shared_ptr
  • それらをメモリ内の完全に異なるコピー(ディープコピー)にしたい場合は、いいえ、使用しないでくださいshared_ptr。ただし、使用することはできますstd::unique_ptrが、コピーセマンティックも実装する必要があります。ただし、この場合はstd::vector<uint8>、独自のクラスを実装する代わりに使用することをお勧めします。

    typedef std::vector<uint8> Message;
    
    Message m1(1024);
    Message m2(m1); //m2 is a deep-copy of m1
    
  • コピーを防止したいので、2番目のステートメントでコンパイルエラーが発生する場合は、次のようにコピーセマンティックを無効にする必要があります=deleteing

    Message(Message const &) = delete;
    Message& operator=(Message const &) = delete;
    

    この場合、移動セマンティックを自分で実装する必要があることに注意してください。通常、移動は理にかなっているので、コメントはしません。

お役に立てば幸いです。

于 2013-01-30T18:06:05.387 に答える
1

コピーと割り当てに関するポリシーは何ですか。クラスをコピーできないようにすると、スマートポインターを使用しても実際の利点はありません。ディープコピーをサポートしているのであれば、その仕事をする標準のスマートポインタはないと思います。自分でコピーと割り当てを実装する必要があります。または std::vector<char>、を使用してください。これですべてが自動的に行われます。浅いコピーをサポートしている場合std::shared_ptrは、その仕事に最適です。

構築後にクラスが不変である場合(すべてのメンバーを表示した場合)、浅いコピーまたはコピーなしが最適です。率直に言って、私はおそらくここstd::stringstd::vectorここを使用し、それについて心配する必要はありません。デフォルトではディープコピーを提供しますが、これはやり過ぎかもしれませんが、確かに最も簡単な解決策です。

于 2013-01-30T18:13:07.477 に答える