8

私はこの問題を抱えています、次のような機能がありfoo()ます、

vector<ClassA> vec;

void foo()
{
    ClassA a;   //inside foo, a ClassA object will be created
    a._ptr = new char[10];

    vec.push_back(a);   //and this newly created ClassA object should be put into vec for later use
}

そして、AFAIKは、のcopy- ctorvecを呼び出して、新しく作成されたオブジェクトのコピーを作成しますが、ここに問題があります。の copy-ctor を通常の方法で定義すると、ClassAaClassA

ClassA::ClassA(const ClassA &ra) : _ptr(0)
{
    _ptr = ra._ptr;
}

オブジェクトaとそのコピー (vec によって作成されたもの) は_ptr同じ領域を指すポインターを持ち、foo終了aするとデストラクタを呼び出して解放_ptrし、aのコピーはvecダングリング ポインターになりますよね? この問題のため、ClassAこのように の copy-ctor を実装したいのですが、

ClassA::ClassA(ClassA &ra) : _ptr(0) //take non-const reference as parameter
{
    std::swap(_ptr, a._ptr);
}

私の実装は大丈夫ですか?または、仕事を達成するのに役立つ他の方法はありますか?

4

5 に答える 5

9

あなたのタイトルの質問に答えるには:はい、Tタイプの必須引数を1つ持つクラスのコンストラクターT &またはT const &(さらにデフォルトの引数を持つこともできます)は、コピーコンストラクターです。C++11 には、 type の引数を 1 つ必要とするmoveT &&コンストラクターもあります。

実際に引数を変更する非定数のコピー コンストラクターを持つと、クラスに非常に珍しいセマンティクス (通常は「転送セマンティクス」) が与えられ、詳細に文書化する必要があります。また、一定のものをコピーすることもできません (明らかに)。古いstd::auto_ptr<T>ものはまさにそれを行います。

可能であれば、新しい C++11 スタイルの変更可能な右辺値参照と移動コンストラクターは、元のオブジェクトでリソースが不要になったときにリソースを "移動" するという問題に対して、はるかに優れたソリューションを提供します。これは、右辺値参照が変更可能なオブジェクトへの参照であるためですstd::moveただし、一時オブジェクトや明示的に ( を介して) キャストし、使い捨てとしてマークしたものなどの「安全な」式にのみバインドできます。

于 2012-07-27T08:25:23.100 に答える
3

C++11 では、まさにこの目的のためにムーブ コンストラクターが導入されました。

ClassA::ClassA(ClassA&& ra)
: _ptr(ra._ptr)
{
    ra._ptr = nullptr;
}

_ptrまたは、共有ポインターであることを宣言することもできます。

std::shared_ptr<char[]> _ptr;

そして、デフォルトのデナレートされたコピーコンストラクターは問題なく機能します。

于 2012-07-27T08:16:49.870 に答える
2

ポインターをコピーするのではなく、ポインターが指しているコンテキストをコピーする必要があります。また、パブリック ポインターにアクセスしてクラスを割り当てるのではなく、必要な要素の数を指定してクラスを初期化する必要があります。

オブジェクトを移動するのではなくコピーする必要があるため、コピーするときに新しいオブジェクトにリソースを割り当てる必要があります。

class A {

        int* p_;
        int size_;
public:

        A(int size) 
        : p_(new int[size]()), 
        size_(size) {
        }

        A(const A &a) 
        : p_(new int[a.size_]),
         size_(a.size_) {               
                std::copy(a.p_, a.p_ + a.size_, p_);
        }

        ...

};


int main () {
        A a(10);
        vec.push_back(a);
}

ただし、コピーするオブジェクトがコピー後に使用されないことがわかっている場合は、代わりにそのリソースを移動できます。

于 2012-07-27T08:32:59.097 に答える
1

The problem with your implementation is that you will not be able to pass temporary objects as arguments for this copy-ctor (temporaries are always const). Like already mentioned the best solution would be to move to c++11 and use move semantics. If it is not possible shared_array can be an alternative.

于 2012-07-27T08:24:47.117 に答える
0

追加コメント:

newオブジェクトを作成し、オブジェクトへのポインターをベクターに格納する際に発生する、この種の問題を回避します。

于 2012-07-27T08:29:28.700 に答える