代码改变世界

Effective C++ 学习笔记(14)

2011-08-03 23:59 by Daniel Zheng, 286 阅读, 0 推荐, 收藏, 编辑
摘要:在operator=中检查给自己赋值的情况做类似下面的事时,就会发生自己给自己赋值的情况:class X { ...};X a;a = a; 这种事做起来好象很无聊,但它完全是合法的,所以看到程序员这样做不要感到丝毫的怀疑。更重要的是,给自己赋值的情况还可以以下面这种看起来更隐蔽的形式出现:a = b; 如果 b 是a 的另一个名字(例如,已被初始化为a 的引用),那这也是对自己赋值,虽然表面上看起来不象。这是别名的一个例子:同一个对象有两个以上的名字。在本条款的最后将会看到,别名可以以大量任意形式的伪装出现,所以在写函数时一定要时时考虑到它。 在赋值运算符中要特别注意可能出现别名的情况,其理 阅读全文

Effective C++ 学习笔记(13)

2011-08-03 22:57 by Daniel Zheng, 198 阅读, 0 推荐, 收藏, 编辑
摘要:在operator=中对所有数据成员赋值template<class T>class NamedPtr{public: NamedPtr(const string & initName, T * initPtr); NamedPtr & operator= (const NamedPtr & rhs);private: string name; T * ptr;};template<class T>NamedPtr<T> & NamedPtr<T>::operator=(const NamedPtr<T> 阅读全文

Effective C++ 学习笔记(12)

2011-08-03 16:03 by Daniel Zheng, 191 阅读, 0 推荐, 收藏, 编辑
摘要:让operator=返回*this的引用要完成如 a = b =c 这样的操作所以返回值不能为void,对这个表达式,编译器的理解为 a = (b = c),所以operator=可以返回左值或者右值,但有时候我们也需要这样的操作 (a = b) = c ,b赋值给a,然后c赋值给a。所以operator=应该返回右值。、由此分析,我们得到operator=的函数声明为 T & T::operator=(const T &)。假设我们传入的参数为a,则a为const T & 类型,与返回类型不符,所以不能作为返回值。如果我们去掉参数的const,首先,这样不安全,函数内 阅读全文

Effective C++ 学习笔记(11)

2011-08-03 15:01 by Daniel Zheng, 239 阅读, 0 推荐, 收藏, 编辑
摘要:确定基类有虚析构函数class A{public: A() { cout<<"A constructor"<<endl; } ~A() { cout<<"A destructor"<<endl; }};class B: public A{public: B() { cout<<"B constructor"<<endl; } ~B() { cout<<"B destructor"<<endl; }};int main() 阅读全文

Effective C++ 学习笔记(10)

2011-08-03 14:28 by Daniel Zheng, 211 阅读, 1 推荐, 收藏, 编辑
摘要:初始化列表中的成员列出的顺序和它们在类中声明的顺序相同class A{public: A(int a):j(a),i(j*2) { cout<<"A constructor"<<endl; } void Get() const { cout<<"i="<<i<<endl<<"j="<<j<<endl; }private: int i; int j;};int main(){ A a(10); a.Get(); return 0;} 执行结果 阅读全文

Effective C++ 学习笔记(9)

2011-08-03 14:12 by Daniel Zheng, 230 阅读, 0 推荐, 收藏, 编辑
摘要:尽量使用初始化而不是在构造函数里赋值class Test{ public: int a; float b; Test():a(0),b(0.0) { } Test() { a=0; b=0.0; }}; 初始化与赋值构造函数对内置类型区别不大,而对于非内置类型,如string,为了避免两次构造函数的调用,推荐使用初始化。以下是必须使用初始化的情况:对于const和引用类型,只能初始化,不能赋值。如果我们的类A有一个类B的成员,而类B没有默认构造函数,而只有带参数的构造函数,这个时候要对类B进行初始化,只能调用初始化表。class A{public: A(int a) { cout<< 阅读全文

(转)C++函数后加const的意义

2011-05-11 10:51 by Daniel Zheng, 2253 阅读, 1 推荐, 收藏, 编辑
摘要:C++函数后加const的意义一些成员函数改变对象,一些成员函数不改变对象。 例如: int Point::GetY() { return yVal; } 这个函数被调用时,不改变Point对象,而下面的函数改变Point对象: void Point:: SetPt (int x, int y) { xVal=x; yVal=y; } 为了使成员函数的意义更加清楚,我们可在不改变对象的成员函数的函数原型中加上const说明:class Point { public: int GetX() const; int GetY() const; void SetPt (int, int); void 阅读全文

Effective C++ 学习笔记(8)

2011-04-14 10:49 by Daniel Zheng, 232 阅读, 0 推荐, 收藏, 编辑
摘要:为需要动态分配内存的类声明一个拷贝构造函数和一个赋值操作符 下面是一个表示String对象的类: class String { public: String(const char *value); ~String(); ... private: char *data; }; String::String(const char *value) { if(value) { data=new char[strlen(value)+1]; strcpy(data,value); } else { data=new char[1]; *data='\0'; } } inline Stri 阅读全文

Effective C++ 学习笔记(7)

2011-04-13 11:05 by Daniel Zheng, 223 阅读, 0 推荐, 收藏, 编辑
摘要:析构函数里对指针成员调用delete 大多数情况下,执行动态内存分配的类都在构造函数中使用new分配内存,然后在析构函数中使用delete释放内存。当这个类经过维护,升级后,情况将变得复杂。每增加一个指针成员都有进行如下的操作: 在每个构造函数中对指针初始化。指向相应的内存地址或者初始化为0,即空指针。 删除现有内存,通过赋值操作符分配给指针新的内存。 在析构函数里删除指针。 对于一个没有用到new去初始化的指针,不用delete去删除。 阅读全文

Effective C++ 学习笔记(6)

2011-04-13 10:17 by Daniel Zheng, 267 阅读, 0 推荐, 收藏, 编辑
摘要:对应的new和delete要采用相同的形式 我们看下面的代码: string *stringArray=new string[100]; ... delete stringArray; 上述代码看上去没错,实际上程序的运行情况将是不可预测的。stringArray指向的100个string对象中的99个不会被正确的摧毁,因为他们的析构函数永远不会被调用。 使用new的会触发两件事情。首先内存被分配,然后为被分配的内存调用一个或多个构造函数。同样,调用delete时也会触发两件事情。首先是为将被释放的内存调用一个或多个析构函数,然后是释放内存。这里,对于一个delete操作而言会有这么一个问题: 阅读全文