C++:make_shared会调用拷贝构造的问题

文章描述了一个在C++中实现观察者模式时遇到的问题,即使用`make_shared`创建对象并添加到列表中导致了拷贝构造函数的调用。由于原始类中的数据成员`m_pData`在拷贝构造后未正确处理,导致析构时出现异常。作者通过在拷贝构造函数中将`m_pData`设为`nullptr`解决了这个问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

闲来无事,想学习学习C++,就随手写了个简单的观察者模式,代码如下:

头文件:

observer.h

#pragma once
#include <iostream>
#include <memory>
#include <list>

//观察者接口
class IObserver
{
public:
	virtual void work() = 0;
	virtual ~IObserver() {}
};
using pObserver = std::shared_ptr<IObserver>;

//被观察者接口
class ISubject
{
public:
	virtual void attach(pObserver obs) = 0;
	virtual void remove(pObserver obs) = 0;
	virtual void notify() = 0;

	virtual ~ISubject() {}
};

//被观察者
class CMaster : public ISubject
{
public:
	void attach(pObserver obs)override;
	void remove(pObserver obs)override;
	void notify()override;

private:
	std::list<pObserver> m_listObs;
};

class CBranch1 :public IObserver
{
public:
	explicit CBranch1()
	{
		m_pData = nullptr;
	}

	CBranch1(const CBranch1 &)
	{
		std::cout << "CBranch1 copy construct.\n";
	}

	CBranch1(const int size)
		:m_pData(new int[size])
	{
		std::cout << "CBranch1 construct.\n";
	}

	~CBranch1()
	{
		if (m_pData)
		{
			delete[] m_pData;
			m_pData = nullptr;
			std::cout << "CBranch1 deconstruct.\n";
		}
	}

public:
	void work();

private:
	void implement();

private:
	int	  *m_pData;
}; 

class CBranch2 :public IObserver
{
public:
	void work();

private:
	void implement();
};

源文件:

observer.cpp

#include "Observer.h"

void CMaster::attach(const pObserver obs)
{
	m_listObs.push_back(obs);
}

void CMaster::remove(const pObserver obs)
{
	auto pos = std::find(m_listObs.begin(), m_listObs.end(), obs);
	if (pos != m_listObs.end())
	{
		m_listObs.remove(obs);
	}
}

void CMaster::notify()
{
	for (const auto& e : m_listObs)
	{
		e->work();
	}
}

void CBranch2::work()
{
	implement();
}

void CBranch2::implement()
{
	int count = 0;
	while (count < 20)
	{
		count++;
		if (count % 2 == 0)
			std::cout << "Branch2 implement()\n";
	}
}

void CBranch1::work()
{
	implement();
}

void CBranch1::implement()
{
	int count = 20;
	while (--count)
	{
		if (count % 2 == 0)
			std::cout << "Branch1 implement()\n";
	}
}

main.cpp

#include "Observer.h"

int main()
{
	//CBranch1 cb1(10);
	CBranch1 cb1;
	CBranch2 cb2;
	CMaster cm;
	cm.attach(std::make_shared<CBranch1>(cb1));
	cm.attach(std::make_shared<CBranch2>(cb2));
	cm.notify();

	getchar();
	return 0;
}

为了省事,给观察者类包了个智能指针,所以在使用时,通过make_shared传一个智能指针对象进入被观察者的List中,但是这里我遇到了问题,程序跑完的结果如下:
控制台
再按回车之后就会出现:
在这里插入图片描述
经过一番调试发现:make_shared函数使用时会调用使用对象类的拷贝构造函数,而再拷贝构造函数被调用后,CBranch1 类中的被置空了的data指针又不知怎么地,被赋予了一个莫名其妙的值(0xcdcdcd),这就导致在最后析构时,这个为空的指针又被delete了一次,从而导致了程序异常,我在拷贝构造中,又加了一句:

m_pData = nullptr;

才解决了问题。
有没有大佬懂这个问题的,求传授解惑!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值