一、来源

这是关于C++定义Vector类作业中出现的问题
作业要求如下:

向量是一种很重要的数据类型,表达了一个相同类型数据的有序集合。定义一个向量类
Vector(开头字母不能用小写,否则会冲突),使得向量类型具有如下性质和功能:
(1)向量元素个数没有限制。
(2)向量对象可分为行向量和列向量,提供向量的转置操作,行向量转置变为列向量,列
向量转置变为行向量。
(3)相同维数的向量加法、减法,向量的加法和减法仍然是一个向量,结果向量的每个元
素为两个向量对应元素的和或差。
(4)相同维数的向量内积,行向量乘以列向量结果为一个标量(单个值)。
(5)获取向量的维数。
(6)获取向量的最大容量。
(7)向量的下标操作获取向量的一个元素。
(8)向量值的输入和输出。
(9)可在向量的空间尾部追加元素,可按照向量中元素的位置删除向量元素。
注:
(1)对象中的向量元素容量采用动态方法(使用堆空间)。动态方法中,一般初始容量是初始向量元素个数的 2 倍。一旦向量元素增加到大于容量,就需要重新申请新的堆空间,新的堆空间容量应该要翻倍,需要将原向量中的元素值复制到新的空间中,然后删除原有的堆空间,当然这样的操作对于对象使用者来说是透明的。
(2)要区分行向量和列向量,可以考虑用添加一个属性标志的方法来解决。
(3)行向量只能加减行向量,列向量只能加减列向量
(4)内积运算符为“*”,只要定义行向量与列向量的运算即可。
(5)向量的维数是指向量的元素个数。

二、初稿

最开始的时候就按自己的思路写了,然后遇到了几个小问题:
(1)关于成员函数返回问题
(2)关于析构问题
类结构:

#pragma once
#ifndef _VECTOR_H
#define _VECTOR_H
class Vector
{
   
	int* v;             	//指向一个数组,表示向量
	int sz;					//容量
	int dms;				//维度
	bool s;					//类型:0->行向量 1->列向量
public:
	Vector();
	Vector(int D, int* Datas,bool ss);		//定义构造函数
	~Vector();							//定义析构函数
	int getsize();						//得到容量
	int getdimension();					//得到维度
	void display();						//输出
	void change();						//类型转化
	int& operator[](int);
	Vector* operator+(Vector&);			//向量加法
	Vector* operator-(Vector&);			//向量减法
	int operator*(Vector&);				//向量点积
	void add(int);						//尾部追加 注意最大容量问题
	void Delete(int);					//定位删除
};//-----------------------------------
#endif

(1)关于成员函数返回问题

写第一稿的时候因为想避开返回是引用还是直接返回,就用了指针返回,但是后来想了想还是不太好,用指针返回不能实现累加。

Vector* Vector::operator+(Vector& another)
{
   
	if (this->dms != another.dms)
		return NULL;
	else
	{
   
		Vector* result;                  //定义Vector类指针表示运算结果
		result = new Vector(this->dms,this->v,this->s);      //为结果分配空间
		int i;
		for (i = 0; i < dms; i++)
			result->v[i] = this->v[i] + another.v[i];
		return result;
	}
}

为了解决累加问题,最后还是把指针改掉了,而很显然,对于局部类result,是不能引用返回的,而直接返回由于类中*v的存在就需要重新定义复制构造函数。
有了复制构造函数后,成员函数就变成了这样:

Vector Vector::operator+(Vector& another)
{
   
	Vector temp(another);
	if (this->dms != another.dms)
		return 0;
	else
	{
   
		int i;
		for (i = 0; i < dms; i++)
			temp.v[i] = this->v[i] + another.v[i];
		return temp;
	}
}

而这个函数的改变,自然而然的带来了下一个问题:

(2)关于析构问题

用默认的析构函数无法解放申请的空间。
而简单的定义:

Vector::~Vector()
{
   
	delete[] v;
}

则会引发断点。
本来是想像之前一次作业一样出现断点索性不析构了,把这个工作留给计算机好了。但是考虑再三还是把它改过来,比较以后一定还会遇到这样的问题。
不知道为什么(希望有大佬解惑)这样不能判断空指针?或许是思路有问题,求指点

Vector::~Vector()
{
   
	if ( v != 0 )
		delete[] v;
}

后来分步调试的时候发现解放空间后那些指针指向值(也就是v[0]的值)变成了-572552307,就换了一种思路:

Vector::~Vector()
{
   
	if (v[0] > -50000000)
		delete[] v;
}

最后顺利编译

三、代码

//vector.h
#pragma once
#ifndef _VECTOR_H
#define _VECTOR_H
class Vector
{
   
	int* v;             	//指向一个数组,表示向量
	int sz;					//容量
	int dms;				//维度
	bool s;					//类型:0->行向量 1->列向量
public:
	Vector();
	Vector(int D, int* Datas,bool ss);		//定义构造函数
	Vector(Vector&);					//复制构造
	~Vector();							//定义析构函数
	int getsize();						//得到容量
	int getdimension();					//得到维度
	void display();						//输出
	void change();						//类型转化
	int& operator[](int);
	Vector operator+(Vector&);			//向量加法
	Vector operator-(Vector&);			//向量减法
	int operator*(Vector&);				//向量点积
	void add(int);						//尾部追加 注意最大容量问题
	void Delete(int);					//定位删除
};//-----------------------------------
#endif
//vector.cpp
#pragma warning(disable:4996)
#include<iostream>
#include "Vector.h"
using namespace std;

Vector::Vector()
{
   
	dms = 0;
	sz = 0;
	s = 0;
	v = NULL;
}
Vector::Vector(int D = 0, int* Datas = NULL,bool ss = 0)//构造函数
{
   
	s = ss;
	dms = D;
	sz = 2 * D;
	v = new int[sz];
	for (int i = 0; i < dms; i++)
		v[i] = Datas[i];
}
Vector::Vector(Vector& other)
{
   
	this->sz = other.sz;
	this->dms = other.dms;
	this->s = other.s;
	v = new int[sz];
	for (int i = 0; i < dms; i++)
		v[i] = other.v[i];
}
Vector::~Vector()
{
   
	if (v[0] > -50000000)
		delete[] v;
}//------------------------------------
int Vector::getsize()
{
   
	return sz;
}
int Vector::getdimension()
{
   
	return dms;
}
void Vector::display()
{
   
	if (s == 0)
		cout << "行向量:" << endl;
	else
		cout << "列向量:" << endl;
	for (int i = 0; i < dms; ++i)
		cout << v[i] << " ";
	cout << "\n";
}
void Vector::change()
{
   
	if (s == 0)
		s = 1;
	else
		s = 0;
}//------------------------------------
int& Vector::operator[](int i) 			//引用返回的目的是返回值可以作左值
{
   
	if (i < 0 || i >= sz)
	{
   
		cerr << "Vector index out of range.\n";
		exit(1);
	}
	return v[i];
}
Vector Vector::operator+(Vector& another)
{
   
	Vector temp(another);
	if (this->dms != another.dms)
		return 0;
	else
	{
   
		int i;
		for (i = 0; i < dms; i++)
			temp.v[i] = this->v[i] + another.v[i];
		return temp;
	}
}
Vector Vector::operator-(Vector& another)
{
   
	Vector temp(another);
	if (this->dms != another.dms)
		return 0;
	else
	{
   
		int i;
		for (i = 0; i < dms; i++)
			temp.v[i] = this->v[i] - another.v[i];
		return temp;
	}
}
int Vector::operator*(Vector& another)
{
   
	if (this->dms != another.dms)
		return -1;
	int ans = 0;
	for (int i = 0; i < dms; i++)
		ans += this->v[i] * another.v[i];
	return ans;
}//------------------------------------
void Vector::add(int a)						//尾部追加 注意最大容量问题
{
   
	if (dms < sz)
	{
   
		v[dms] = a;
		dms++;
	}
	else
	{
   
		sz *= 2;
		int* temp = new int[sz];
		for (int i = 0; i < dms; i++)
			temp[i] = v[i];
		temp[dms] = a;
		delete[] v;
		v = temp;
		dms++;
	}
}
void Vector::Delete(int k)
{
   
	if (k < dms)
	{
   
		for (int i = k - 1; i < dms; i++)
			v[i] = v[i + 1];
		dms--;
	}
	else
		cout << "该向量小于k维度" << endl;
}
#include<iostream>
#include"vector.h"
using namespace std;
#pragma warning(disable:4996)

int main()
{
   
	int a[5] = {
    4,3,5,2,1 };
	int b[5] = {
    6,8,4,9,7 };
	Vector v1(5, a, 0), v2(5, b, 1);
	cout << v1.getdimension() << " " << v1.getsize() << endl;
	v1.display();
	cout << v2.getdimension() << " " << v2.getsize() << endl;
	v2.display();
	//v1.change();
	//cout << v1.getdimension() << " " << v1.getsize() << endl;
	//v1.display();
	cout << "check +-*:" << endl;
	Vector v3 = v1 + v2 + v2;
	v3.display();
	Vector v4 = v1 - v2;
	v4.display();
	int x = v1 * v2;
	cout << x << endl;
	cout << "check add&delete:" << endl;
	v1.add(9);
	v1.display();
	v1.Delete(2);
	v1.display();
	cout << "check different dimension:" << endl;
	v3 = v1 + v2 ;
	cout << "check more size:" << endl;
	for (int i = 10; i < 20; i++)
	{
   
		v1.add(i);
		v1.display();
		cout << v1.getdimension() << " " << v1.getsize() << endl;
	}
	return 0;
}

作:VaQX