c++ - 构造一个以 shared_ptr 作为成员字段的类的正确语法是什么?

标签 c++ c++11 shared-ptr

假设,我想创建一个带有指向另一个类 A 的指针的类 B。在 A 的构造函数中,我想构造 B 并向其传递一个指向 this 的指针。原则上,这个指针可以是一个shared_ptr,对吗?那么如何在构造函数中分配 shared_ptr 来创建这样一个类呢?

我在下面的代码中尝试过。 ClassBClassC 是相同的,都有一个指向 ClassA 的指针,它构造 ClassBClassC< 的实例。唯一的两个区别是,ClassB 持有一个常规指针,而 ClassC 持有一个指向 ClassAshared_ptr,并且代码使用 ClassB 可以正常工作,而使用 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;
}

最佳答案

它们做的不是同一件事:

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

第一个初始化程序使用 this 指针创建一个 ClassB 类型的临时对象,并通过复制该临时对象来初始化 objectB:

objectB(ClassB( this ))

第二个创建一个new ClassA作为*this的拷贝,将其存储在shared_ptr中,然后用该 shared_ptr 初始化一个临时 ClassC,然后通过复制该临时值来初始化 objectC:

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 有一个指向 this 的指针,但 objectB 有一个指向不同<的(共享)指针/em> 对象,即 *this 的拷贝。

shared_ptr 的要点是它拥有您给它的指针,并且(通常)会删除该指针。在对象的构造函数中不能有一个拥有 thisshared_ptr,因为在该对象完成构造之前,它不能被任何 shared_ptr (您给 shared_ptr 的指针是一个指向完整对象的指针,而不是通过其构造函数部分构造的指针),因此没有安全的方法获取一个引用 thisshared_ptr,您可以将其传递给 objectC 的构造函数。有一种方法可以做到这一点,使用 shared_ptr 的别名功能,但我认为您应该重新检查您的设计并询问为什么您想要 objectC >“拥有”它所属的对象......这是没有意义的。

关于c++ - 构造一个以 shared_ptr 作为成员字段的类的正确语法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11192016/

相关文章:

c++ - IEEE 754-2008(密集十进制)的可用实现

c++ - codility MaxDistanceMonotonic,我的解决方案有什么问题

c++ - 字符串用作参数时是否更改 const char *

c++ - 移动构造函数会自动初始化未列出的成员吗?

c++ - 将对虚类实现的引用作为线程参数传递

c++ - 带有 boost shared_ptr 的自定义(池)分配器

c++ - 海湾合作委员会 4.0 : "no matching function to call" in template function

c++ - 具有 const 不可复制元素的元组

c++ - 在 L3 缓存未命中发生之前, vector 中有多少个可迭代对象?

c++ - 确保全局记录器对象的生命周期比其他全局对象长