一、来源
这是关于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