Vector class (1)

原创 2004年09月22日 00:59:00

Referrence:
Jim Blinn, "Optimizing C++ Vector Expression", in IEEE database
Kenneth I. Joy, "the Vector Data Type", http://graphics.cs.ucdavis.edu/CppNotes/homepage.html

PART I: on Constructor:
"All classes should have a copy constructor and an assignment operator."
That means, we should add two functions:
"Vector(const Vector&); and Vecotr& operator=(const Vector&);"
together with
"Vector(const double, const double, const double =0.0)"

原因是安全并且方便 (参考effective C++第三章, rule 11)
and consider that
Vecotr& operator=(const Vector&)
the input and output of operator is the same.

PART II: on output and Serialize
暂时不管他

PART III operator calling
试试严格遵守"没有重复代码的规定"

Vector& operator+=(const Vector& v2)
{
 _x+=v2._x; _y+=v2._y; _z+=v2._z;
 return *this;
}
int operator== (const Vector& v1, const Vector &v2)
{
 if((v1._x==v2._x)&&(v1._y==v2._y)&&(v1._z==v2._z))
    return TRUE;
 else
    return FALSE;
}
在这个基础上,定义
Vector& operator+(const Vector& v1, const Vector &v2)
{
 return Vector(A) +=B;
}
int operator!= (const Vector& v1, const Vector &v2)
{
 return(!(v1==v2));
}
看起来不错,但实际上operator+定义的不好。因为这样增加了一个Vector(A)的创建对象的开销。
我敢肯定matlab不会这样干的。希望下次可以研究一下matlab的早期代码。

Part IV 随心所欲的计算

Part of the vast popularity of C++ is its class structure and operator overloading features
that allow the definition of mathematical operations for many class. We should know we can
make the C++ act as matlab!

接着讨论operator+.如果我们不搞得那么花哨的话我们可以定义operator+的返回值是Vector 而不是Vector&
注意opertator+ 与operator=的情况是完全不一样的!
Vector operator+ (const Vector& v1, const Vector& v2)
{
 Vector vv;
 vv._x = v1._x+v2._x;
 vv._y = v1._y+v2._y;
 vv._z = v1._z+v2._z;
 return(vv);
}

这样可以定义 *, /,-,+.
其他的,matlab里有.*,./,.-,.+.可以试试
另外,定义 Vector cross(const Vector& v1, const Vector& v2);
double dot(const Vector& v1, const Vector& v2);
void Vector::normalize();
double Vector::length();
最后,考虑operator重载,Vector operator+(float f1)等等。
当然,要想像matlab一样随心所欲,还有三件事
1.试试模板之类的东西。matlab可以不管int double 通吃的。
2.和矩阵的计算,接口
3.matlab 可以 d = [a,b,c]. C++好像只能d = vector(a,b,c)了。凑合着用了
这三条,以后再说吧.

Part V 编译错误

这玩意极其让人讨厌。#是万恶之源。std更是把这种罪恶推到了极点。
多用const吧。

1. we should know the difference between const char *p (*p='c' is not allowed)
and char* const p (p++ is not allowed);
2. we should know the reason why Vector dot(const Vector&, const Vector &)
instead of Vector dot(Vector&,Vector &). Yes, one reason is it is more safe.
But another reason, if we define Vector dot(Vector&, Vector &), we will get
errors when using: a = dot(v1+v2,v3). The compiler will not allow you to change
(v1 + v2)!
3. do not forget to declare a const function: double length()const; will not
change the data members of the class.

Part VI 效率
C++运行比较慢就在于创建对象的开销。 一个奇怪的现象是C++大规模矩阵计算未必赶得上matlab.
至于其他的软件,至少我觉得photoshop远远比一般的图像处理程序快的多。优化还是很重要的啊。
上面的Vector实现比较费时的地方是每个operator+里面都要创建一个Vector对象
然而,一个tricky的做法是采用"容器",而不是数据对象

class Sum{
const Vector &L;
const Vector &R;
public:
Sum(const Vector& Linit, const Vector& Rinit):L(Linit),R(Rinit){;}
float operator[](int i)const {return L[i]+R[i];} 
}

void Vector::Evaluate(const Sum& e){
 v[0]=e[0];v[1]=e[1];v[2]=e[2];
}
Sum operator+(const Vector& A,const Vector& B){ 
 return Sum(A,B);
}

恩,这种东西真难维护。 :-P
不过呢,用Visitor模式,定义void Vector::Evaluate(const Function& e),
然后用Function 派生出各个类, Sum, Product....,各个类实现虚函数
operator[]。比如Sum::operator[](int i)是{return L[i]+R[i]}
而Product::operator[](int i)则是{return s*V[i]}.
漂亮把?
----yes, but.... do you know the cost of virtual function?
根据Berlin的结果,用Visitor模式的效率还不如最土的办法。:-(

在effective c++中,41号条款告诉我们,
"如果类型T不影响类的行为T,你可以使用模板。如果T影响行为,你就需要虚函数,从而要使用继承。"
能不能把上面的trick用template 表示呢? 模板的效率好像还不错,想想stl就知道了
ok,let's go

//Sum<L,R>
template<class LT,class RT>
class Sum{
const LT &L;
const RT &R;
public:
Sum(const LT& Linit, const RT& Rinit):L(Linit),R(Rinit){;}
float operator[](int i)const{return L[i]+R[i];} 
};

//Product<V>
template<class VT>
class Product{
float s;
const VT& V;
public:
Product(const float sinit,const VT& Vinit):s(sinit),V(Vinit){;}
float operator[](int i)const{return s*V[i];}
};

// class Vector
class Vector{
...
template <class T>
Vector(const T& e){
 Evaluate(e);
}

template<class T>
void Evaluate(const T& e){
 v[0]=e[0];v[1]=e[1];v[2]=e[2];
}

template<class T>
Vector& operator=(const T& e){
 Evaluate(e);
 return this;
}
}
什么感觉?...有一点喘不过来气了。

看起来已经到了极限了。但是这只是针对3*Vector 或者Vector + Vector来说的。
想想如果计算a+3*(b+c),实际上是Sum(Vector,Product(Sum(Vector,Vector))).我们能不能将中间步骤
进一步简化呢?
可以的。不过需要进一步使用template.这个以后再看吧。可以去看Blinn的文章。

最后抄一段Blinn的话

Every programming language has a gimmick.
The gimmick of C++ is to put as much intelligence in the class library as possible,
to make things as easy as possible for the user of the those class. In spite of the fact
that there is a lot of complexity in the implementation of vector arithmetic, any user of
the Vector class does not see that complexity. They can create Vector class and perform
arithmetic on them with ease and with confidence. That is the classical trade-off in C++:
the need of the many out weigh the needs of  the few.

最后一句很精彩。但也许允许我有一点不同意见。class不但要便于使用,也要便于维护。除非真的有速度
的工程需要,否则我想我愿意牺牲速度来换取可读性的。但是Cpp的可读性不一定是多重继承,接口,模板
也许更重要。我想考虑的是复杂的数据结构。比如一个从点的邻接矩阵找面,什么数据结构比较好,什么class
设计比较清晰?

那么回到Vector的讨论上来,如果我想Vector便于维护,至少可以从两个角度来想
第一,如果要将Vector扩展到4d, 也就是说homogeneous coordinates,那么Vector类的设计要怎么办?
第二,考虑Vector 和Matrix间的接口,应该怎么设计?

前一个可以去看Vxl,后一个可以去看matlab的设计。不过我要先自己想想。下次再写

vector<class A> 与 vector<class *A>

vector 与 vector “动态加入”的代码有问题,最好不要用。 其一,vector中存的是指针,如果class A有析构函数,copy,move,delete都会出问题。 其二,new ...
  • MAZHEN1986
  • MAZHEN1986
  • 2012年03月21日 22:53
  • 1576

<vector> template实现

#include /********************************* vector *******************************************...
  • Decload
  • Decload
  • 2012年01月23日 14:45
  • 1616

STL vector方法总结(一)Member functions(34)

这里是vector的所有构造方法,成员方法的一些总结,具体的可以详看后面的链接。 容器:Vector 原型: template > class vector;  描述:vector是一种顺序容器,其...
  • guang_jing
  • guang_jing
  • 2014年08月27日 11:03
  • 1075

error LNK2005: “public: class std::vector<class std::vector<class std::vector<float>”

VS2010:error LNK2005: "public: class std::vector
  • sdgtliuwei
  • sdgtliuwei
  • 2015年02月06日 18:29
  • 873

使用vector的编译错误

#include      #include                    using   namespace   std;     //A   void   main()   {     v...
  • chaoi
  • chaoi
  • 2007年05月28日 15:53
  • 4860

实战c++中的vector系列--对vector<自定义类>使用std::find 和 std::find_if 算法

之前博客讲了一些关于std::find和std::find_ if的一些用法,但是没有讲述对于vector中存储的是自定义的类,那么怎么样使用std::find和std::find_if进行查找呢?先...
  • wangshubo1989
  • wangshubo1989
  • 2015年12月23日 21:19
  • 8038

Introduction to One-class Support Vector Machines

Traditionally, many classification problems try to solve the two or multi-class situation. The goal ...
  • u010159842
  • u010159842
  • 2016年12月06日 16:11
  • 738

简单的vector实现

学习c++中,看完书后,最近苦于不知道下一步该怎么办了,就翻翻STL源码剖析中的各种容器,想重新实现一遍。很多问题之前看的时候还不知道是怎么回事,当自己写的时候才发现许多应该注意与理解的。这个vect...
  • u012637838
  • u012637838
  • 2014年11月01日 16:40
  • 790

leetcode题目总结<1>

开始了leetcode的刷题之路,话不多说,从头开始,日积月累。 344.Reverse String //my code #include using namespace std; class ...
  • dby3579
  • dby3579
  • 2016年08月11日 21:02
  • 817

C++Primer 第四版的代码问题

MS_files\3: 1  init_vec.cpp(45) : error C2653: 'vector >' : is not a class or namespace name  加上...
  • mlj318
  • mlj318
  • 2011年10月13日 13:07
  • 944
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Vector class (1)
举报原因:
原因补充:

(最多只允许输入30个字)