2

B別のクラスへのポインタを持つクラスを作成したいとしますA。のコンストラクターで、Aへのポインターを作成Bして渡しますthis。原則として、このポインタはshared_ptr正しいですか?shared_ptrでは、コンストラクターでの割り当てを使用して、このようなクラスを作成するにはどうすればよいですか?

以下のコードで試してみました。ClassBClassCは同一であり、とのClassAインスタンスを構成するポインタがClassBありますClassC。唯一の2つの違いはClassB、通常のポインターをClassC保持し、shared_ptrtoClassAを保持し、withのコードClassBが機能し、withのコードが機能しClassCないことです。私は何が間違っているのですか?

// Main.cpp : Defines the entry point for the console application.

#include "ClassA.h"
#include <iostream>

int main(int argc, char* argv[])
{
    std::cout << "Create B and C separately, without a reference to A:" << std::endl;
    ClassB(nullptr);
    ClassC(nullptr);

    std::cout << "Create A, and through it B and C:" << std::endl;
    ClassA A;

    A.PrintHello();
    A.getObjectB().getPointerToA()->PrintHello();

    A.PrintHello();
    A.getObjectC().getPointerToA()->PrintHello();
    return 0;
}

// ClassA.h

#pragma once

#include "ClassB.h"
#include "ClassC.h"

class ClassA
{
private:
    ClassB objectB;
    ClassC objectC;

public:
    ClassA(void);

    ClassB getObjectB() { return objectB; };
    ClassC getObjectC() { return objectC; };

    void PrintHello();
};

// ClassA.cpp

#include "ClassA.h"
#include <iostream>
#include <memory>

ClassA::ClassA(void) : objectB(ClassB( this )), objectC(ClassC( std::make_shared<ClassA>(*this) ))
{
    std::cout << "Class A fully constructed" << std::endl;
}

void ClassA::PrintHello()
{
    std::cout << "Hello" << std::endl;
}

// ClassB.h

#pragma once

#include <memory>

class ClassA;

class ClassB
{
private:
    ClassA* pointerToA;

public:
    ClassB(ClassA* pA);

    ClassA* getPointerToA() { return pointerToA; };
};

// ClassB.cpp

#include "ClassB.h"
#include <iostream>

ClassB::ClassB(ClassA* pA) : pointerToA(pA)
{
    std::cout << "Class B constructed" << std::endl;
}

// ClassC.h

#pragma once

#include <memory>

class ClassA;

class ClassC
{
private:
    std::shared_ptr<ClassA> pointerToA;

public:
    ClassC(std::shared_ptr<ClassA> pA);

    std::shared_ptr<ClassA> getPointerToA() { return pointerToA; };
};

// ClassC.cpp

#include "ClassC.h"
#include <iostream>

ClassC::ClassC(std::shared_ptr<ClassA> pA) : pointerToA(pA)
{
    std::cout << "Class C constructed" << std::endl;
}
4

2 に答える 2

4

これらは同じことをしていません:

ClassA::ClassA(void) : objectB(ClassB( this )), objectC(ClassC( std::make_shared<ClassA>(*this) ))

最初の初期化子はClassBthisポインターを使用してタイプの一時的なものを作成し、objectBその一時的なものをコピーして初期化します。

objectB(ClassB( this ))

2つ目は、のコピーとしてnew を作成し、それをに格納し、それを使用して一時を初期化し、次にその一時をコピーして初期化します。ClassA*thisshared_ptrClassCshared_ptrobjectC

objectC(ClassC( std::make_shared<ClassA>(*this) ))

構文は不必要に冗長です。一時的なものを避け、メンバーを直接コピーして初期化します。

    objectB( this ), objectC( std::make_shared<ClassA>(*this) )

これは次と同等です。

    objectB( this ), objectC( std::shared_ptr<ClassA>( new ClassA(*this) ) )

は別のオブジェクトへのポインタを持っていますが、別のオブジェクト、つまりのコピーへの(共有)ポインタをobjectB持っていることは明らかです。thisobjectB*this

aのポイントは、shared_ptr指定したポインターを所有し、(通常は)ポインターを削除することです。shared_ptrオブジェクトのコンストラクターにを所有することはできませんthis。オブジェクトの構築が完了するまで、オブジェクトを所有することはできないためです(aに指定するポインターは、部分的に構築された半分ではなく、完全なshared_ptrオブジェクトへのポインターです。コンストラクターを経由する)ので、のコンストラクターに渡すことができる参照を取得する安全な方法はありません。のエイリアシング機能を使用してそれを行う方法はありますが、デザインを再検討して、その一部であるオブジェクトを「所有」する理由を尋ねる必要があると思います...それは意味がありません。shared_ptrshared_ptrthisobjectCshared_ptrobjectC

于 2012-06-25T17:47:11.620 に答える
1

std::make_shared新しいオブジェクトを割り当てて初期化します。

于 2012-06-25T15:56:49.840 に答える