[英]What is the correct syntax to construct a class with a shared_ptr as member field?
Suppose, I want to make a class B
with a pointer to another class A
. 假设我想用一个指向另一个类
A
的指针来创建一个类B
In the constructor of A
I want to construct B
and passing it a pointer to this
. 在
A
的构造函数中,我想构造B
并将其指针传递给this
。 In principle, this pointer can be a shared_ptr
, correct? 原则上,该指针可以是
shared_ptr
,对吗? Then how do I make such a class with the assignment of the shared_ptr
in the constructor? 那么,如何在构造函数中分配
shared_ptr
来创建此类?
I tried it in the code below. 我在下面的代码中尝试过。
ClassB
and ClassC
are identical, with a pointer to ClassA
which constructs instances of ClassB
and ClassC
. ClassB
和ClassC
是相同的,但指向ClassA
的指针构成了ClassB
和ClassC
实例。 The only two differences are that ClassB
holds a regular pointer and ClassC
holds a shared_ptr
to ClassA
and that the code with ClassB
is working and the code with ClassC
is not. 仅有的两个区别是,
ClassB
持有一个常规指针,而ClassC
持有一个指向ClassA
的shared_ptr
,带有ClassB
的代码正常工作,而带有ClassC
的代码无效。 What am I doing wrong? 我究竟做错了什么?
// 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;
}
These are not doing the same thing: 这些不是在做同一件事:
ClassA::ClassA(void) : objectB(ClassB( this )), objectC(ClassC( std::make_shared<ClassA>(*this) ))
The first initializer creates a temporary of type ClassB
with the this
pointer and initializes objectB
by copying that temporary: 第一个初始化程序使用
this
指针创建一个ClassB
类型的临时对象,并通过复制该临时objectB
来初始化objectB
:
objectB(ClassB( this ))
The second creates a new ClassA
as a copy of *this
, stores it in a shared_ptr
, then initializes a temporary ClassC
with that shared_ptr
, then initializes objectC
by copying that temporary: 第二个创建一个新的
ClassA
作为*this
的副本,将其存储在shared_ptr
,然后使用该shared_ptr
初始化一个临时的ClassC
,然后通过复制该临时的类来初始化objectC
:
objectC(ClassC( std::make_shared<ClassA>(*this) ))
Your syntax is unnecessarily verbose, avoid the temporaries and copies and initialize your members directly: 您的语法不必要地冗长,请避免使用临时变量并直接复制并初始化成员:
objectB( this ), objectC( std::make_shared<ClassA>(*this) )
This is equivalent to: 这等效于:
objectB( this ), objectC( std::shared_ptr<ClassA>( new ClassA(*this) ) )
It should be clear that objectB
has a pointer to this
but objectB
has a (shared) pointer to a different object, that is a copy of *this
. 应该清楚的是,
objectB
有一个指向this
的指针,但是objectB
有一个(共享的)指向另一个对象的指针,该对象是*this
的副本。
The point of a shared_ptr
is it owns the pointer you give it, and will (generally) delete the pointer. shared_ptr
的要点是它拥有您赋予它的指针,并且(通常)将删除该指针。 You can't have a shared_ptr
that owns this
in an object's constructor, because until the object has finished being constructed it can't be owned by any shared_ptr
(the pointer you give to a shared_ptr
is a pointer to a complete object, not a partially constructed one half way through it's constructor) so there's no safe way to get a shared_ptr
referring to this
that you can pass to objectC
's constructor. 你不能有一个
shared_ptr
拥有this
在对象的构造函数,因为直到对象已完成正在建设它不能被任何所拥有shared_ptr
(你给一个指针shared_ptr
是一个指向一个完整的对象,而不是部分通过其构造函数的一半构造),因此没有安全的方法可以获取指向this
的shared_ptr
并传递给objectC
的构造函数。 There is a way to do it, using the aliasing feature of shared_ptr
but I think you should re-examine your design and ask why you want objectC
to "own" the object it's part of ... that doesn't make sense. 有一种方法可以使用
shared_ptr
的别名功能来实现,但是我认为您应该重新检查您的设计,并询问为什么要让objectC
“拥有”对象的一部分……这是没有道理的。
std::make_shared
分配并初始化一个新对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.