初夏小谈:vector的模拟实现(二)解决浅拷贝问题

上次实现的vector中存在这样的问题:就是在扩容中用memcpy来进行元素的拷贝,但是它会拷贝数据的位置,到另一块空间中。这样在后面的释放原来的空间后,这一份资源就会被释放,从而这块新空间指向的资源将会失效。程序就会发生崩溃。所以就进行深拷贝。

代码如下:

#include<iostream>
#include<vector>
using namespace std;

namespace FirstVector
{
	template<class T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef T* reverse_iterator;
	public:
		//******************************************************************************
		//第一种基本操作
		//1.构造
		vector()
			: _start(nullptr)
			, _finish(nullptr)
			, _endOfStorage(nullptr)
		{}
		//1.2
		vector(size_t n, const T& data = T())
		{
			_start = new T[n];
			for (size_t i = 0; i < n; i++)
			{
				_start[i] = data;
			}
			_finish = _start + n;
			_endOfStorage = _finish;
		}
		//1.3
		vector(T*first, T*last)
		{
			size_t size = last - first;
			_start = new T[size];
			_finish = _start;
			T* First = first;
			while (First != last)
			{
				*_finish = *First;
				First++;
				_finish++;
			}
			_endOfStorage = _finish;
		}
		//拷贝构造函数
		//注意浅拷贝的问题
		vector(vector<T>& v)
		{
			size_t VSize = v.size();
			_start = new T[VSize];
			_finish = _start;
			for (size_t i = 0; i < VSize; i++)
			{
				*_finish++ = v[i];
			}
			_endOfStorage = _finish;
		}

		//赋值运算符的重载
		vector<T>& operator=(const vector<T>& v)
		{
			if (this != &v)
			{
				size_t VSize = v.size();
				_start = new T[VSize];
				_finish = _start;
				for (int i = 0; i < VSize; i++)
				{
					*_finish++ = v[i];
				}
				_endOfStorage = _finish;
			}
		}

		//析构
		~vector()
		{
			if (_start)
			{
				delete[] _start;
				_start = nullptr;
				_finish = nullptr;
				_endOfStorage = nullptr;
			}
		}
		//******************************************************************************
		//迭代器
		//1.返回首位置begin
		iterator begin()
		{
			return _start;
		}

		//2.返回末尾位置end
		iterator end()
		{
			return _finish;
		}

		//3.反向迭代器
		//首位置rbegin
		reverse_iterator rbegin()
		{
			return end();
		}

		//4.末尾位置rend
		reverse_iterator rend()
		{
			return begin();
		}
		//******************************************************************************
		//容量相关操作
		//1.获取容量有效元素的个数
		size_t size()const
		{
			return _finish - _start;
		}

		//2.获取容量的大小
		size_t capacity()const
		{
			return _endOfStorage - _start;
		}

		//3.判断有没有元素
		bool empty()
		{
			return _finish == _start;
		}

		//4.扩容
		void reserve(size_t NewCapacity)
		{
			size_t OldCapacity = capacity();
			if (NewCapacity > OldCapacity)
			{
				T* temp = new T[NewCapacity];
				size_t OldSize = size();
				if (_start)
				{
					//T:是否为内置类型? typeid(T).name()
					//编译期间确定
					//深拷贝
					//优点:一定不会出粗
					//缺点:效率低
					for (size_t i = 0; i < OldSize; i++)
					{
						temp[i] = _start[i];
					}
					//浅拷贝
					//memcpy优点:效率高 缺陷:浅拷贝,遇到自定义对象可能会出错
					//memcpy(temp, _start, size()*sizeof(T));
					delete[] _start;
				}
				_start = temp;
				_finish = _start + OldSize;
				_endOfStorage = _start + NewCapacity;
			}
		}

		//5.设置有效元素个数
		void resize(size_t NewSize, const T& data = T())
		{
			size_t OldSize = size();
			size_t _Capacity = capacity();
			if (NewSize > OldSize)
			{
				if (NewSize > _Capacity)
				{
					reserve(NewSize);
				}
				
				for (size_t i = OldSize; i < NewSize; i++)
				{
					*(_finish++) = data;
				}

			}
			else if (NewSize < OldSize)
			{
				_finish = _start + NewSize;
			}
		}
		//*******************************************************************************
		//元素访问操作
		//const
		//1.随机访问
		T operator[](size_t index)
		{
			size_t OldSize = size();
			if (index >= OldSize)
			{
				return NULL;
			}
			//assert(index < OldeSize);
			return _start[index];
		}

		const T* operator[](size_t index)const
		{
			size_t OldSize = size();
			if (index >= OldSize)
			{
				return nullptr;
			}
			//assert(index < OldeSize);
			return _start[index];
		}

		//2.访问头部元素
		T& front()
		{
			return _start[0];
		}

		const T& front()const
		{
			return _start[0];
		}
		//3.访问尾部元素
		T& back()
		{
			return *(_finish - 1);
		}
		const T& back()const
		{
			return *(_finish - 1);
		}
		//********************************************************************************
		//元素修改操作
		//1.尾部插入元素
		void push_back(const T& data)
		{
			if (_finish == _endOfStorage)
			{
				size_t OldCapacity = capacity();
				reserve(2 * (OldCapacity + 1));
			}
			*(_finish++) = data;
		}

		//2.尾部删除元素
		void pop_back()
		{
			if (_finish == _start)
			{
				return;
			}
			_finish--;
		}

		//iterator
		//3.任意位置插入
		iterator insert(iterator position, const T& data)
		{
			if (_finish == _endOfStorage)
			{
				size_t OldCapacity = capacity();
				reserve(2 * (OldCapacity + 1));
			}
			size_t OldSize = size();
			if (position <= OldSize)
			{
				for (size_t i = OldSize; i > position; i--)
				{
					_start[i] = _start[i - 1];
				}
				_start[position] = data;
				_finish++;
			}
		}

		//iterator
		//4.任意位置删除
		iterator erase(iterator position)
		{
			size_t OldSize = size();
			if (position >= OldSize)
			{
				return;
			}
			for (size_t i = position; i < OldSize; i--)
			{
				_start[i] = _start[i + 1];
			}
			_finish--;
		}

	private:
		T* _start;
		T* _finish;
		T* _endOfStorage;
	};
}

//memset设置一个字节//

//打印vector
template<class T>
void PrintVector(FirstVector::vector<T>& v)
{
	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;
}

//测试三种构造函数以及容量相关操作
void TestVector()
{
	FirstVector::vector<int> v1;
	FirstVector::vector<int> v2(10, 5);
	int array[] = { 1,2,3,4,5,6,7,8,9,0 };
	FirstVector::vector<int> v3(array, array + sizeof(array) / sizeof(array[0]));

	cout << v1.empty() << endl;
	cout << v1.size() << endl;
	cout << v1.capacity() << endl;
	PrintVector(v1);
	v1.resize(6);
	v1.reserve(10);
	cout << v1.size() << endl;
	cout << v1.capacity() << endl;

	cout << v2.empty() << endl;
	cout << v2.size() << endl;
	cout << v2.capacity() << endl;
	PrintVector(v2);
	v2.resize(6);
	v2.reserve(12);
	cout << v2.size() << endl;
	cout << v2.capacity() << endl;


	PrintVector(v3);
	
}

//测试拷贝构造以及复制运算符重载
void TestVector1()
{
	FirstVector::vector<int> v1(10, 5);
	FirstVector::vector<int> v2(v1);
	FirstVector::vector<int> v3 = v1;
	cout << v1.size() << endl;
	cout << v1.capacity() << endl;
	cout << v2.size() << endl;
	cout << v2.capacity() << endl;
	cout << v3.size() << endl;
	cout << v3.capacity() << endl;
	PrintVector(v1);
	PrintVector(v2);
	PrintVector(v3);
}

//测试元素访问系列操作
void TestVector2()
{
	int array[] = { 1,2,3,4,5,6,7,8,9,0 };
	FirstVector::vector<int> v4(array, array + sizeof(array) / sizeof(array[0]));
	cout << v4[5] << endl;
	cout << v4.front() << endl;
	cout << v4.back() << endl;
	PrintVector(v4);
}

//测试元素修改系列操作
void TestVector3()
{
	FirstVector::vector<int> v5(15, 6);
	cout << v5.size() << endl;
	v5.push_back(8);
	cout << v5.back() << endl;
	cout << v5.size() << endl;

	v5.pop_back();
	cout << v5.back() << endl;
	cout << v5.size() << endl;
	PrintVector(v5);

	//FirstVector::vector<int>::iterator v6(10, 8);
}


//************************************************************************************************
//迭代器失效:迭代器本质:指针--->指针失效--->指针指向了非法的空间
//迭代器指向的空间改变,而迭代器依旧指向原来的空间
//1.容量发生改变(赋值,插入,resize,reserve等等)
//2.当前迭代器所指向的元素删除(erase)
void TestVector5()
{
	vector<int> v{ 1,2,3,4,5 };
	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;
	vector<int>::iterator it = v.begin();
	v.reserve(16);
	it = v.begin();
	cout << "*it = " << *it << endl;
}

void TestVector6()
{
	vector<int> v{ 1,2,3,4,5 };
	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;
	vector<int>::iterator it = v.begin();
	while (it != v.end())
	{
		//v.erase(it);	
		it = v.erase(it);
		for (auto& e : v)
		{
			cout << e << " ";
		}
		cout << endl;
	}
}
//it = v.erase(it);
//for (auto& e : v)
//{
//	cout << e << " ";
//}
//cout << endl;
int main()
{
	TestVector6();
	system("pause");
	return 0;
}
//********************************************************************************************

浅拷贝:优点:效率高。但是存在问题就是遇到自定义对象可能会出错。

深拷贝:优点:一定不会出错。但是效率低。

所以在是否用深拷贝还是浅拷贝时,根据具体情况而定,二者综合使用也是可以。

                                                                                                                                                 珍&源码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,您的问题是如何使用多线程对像素点进行灰度化操作的C#实现,并且解决线程安全问题。 对于像素点灰度化的操作,可以使用C#提供的`Bitmap`类来实现。而多线程的实现可以使用`Parallel.For`方法来实现。为了解决线程安全问题,可以使用`lock`语句来保证多个线程不会同时访问同一个`Bitmap`对象。 具体实现步骤如下: 1. 将像素点的灰度化操作封装成一个函数。 ```c# private static void GrayPixel(Bitmap bmp, int x, int y) { // 获取像素点的颜色值 Color color; lock (bmp) { color = bmp.GetPixel(x, y); } // 计算像素点的灰度值 int gray = (int)(color.R * 0.299 + color.G * 0.587 + color.B * 0.114); // 更新像素点的值为灰度值 lock (bmp) { bmp.SetPixel(x, y, Color.FromArgb(gray, gray, gray)); } } ``` 2. 在主函数中,使用`Parallel.For`方法启动多线程对图像的像素点进行灰度化操作。 ```c# static void Main(string[] args) { // 读取图像 Bitmap bmp = new Bitmap("test.jpg"); // 获取图像的宽度和高度 int width = bmp.Width; int height = bmp.Height; // 启动多线程 Parallel.For(0, height, y => { for (int x = 0; x < width; x++) { GrayPixel(bmp, x, y); } }); // 显示灰度化后的图像 bmp.Save("gray.jpg"); } ``` 上述代码中,在`GrayPixel()`函数中使用了`lock`语句来保证多个线程不会同时访问同一个`Bitmap`对象。同时,在`Parallel.For`方法中,每个线程只会处理自己分配的像素点,不会造成线程之间的干扰。 最后,保存灰度化后的图像。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值