随笔分类 -  effective c++

摘要:假设想写一个类模板Array,它所生成的类除了可以进行上下限检查外,其它行为和C++标准数组一样。设计中面临的一个问题是怎么禁止掉Array对象之间的赋值操作,因为对标准C++数组来说赋值是不合法的:double values1[10];double values2[10];values1 = va... 阅读全文
posted @ 2014-08-16 14:29 合唱团abc 阅读(142) 评论(0) 推荐(0)
摘要:class B; // 对类B提前声明 // class A {public: A(const B&); // 可以从B构造而来的类A};class B {public: operator A() const; // 可以从A转换而来的类B};void f(c... 阅读全文
posted @ 2014-08-16 14:26 合唱团abc 阅读(184) 评论(0) 推荐(0)
摘要:class rational {public: rational(int numerator = 0, int denominator = 1); ...private: int n, d; // 分子和分母friend const rational ... 阅读全文
posted @ 2014-08-16 14:00 合唱团abc 阅读(317) 评论(0) 推荐(0)
摘要:c语言中,什么都是通过传值来实现的,c++继承了这一传统并将它作为默认方式。除非明确指定,函数的形参总是通过“实参的拷贝”(拷贝构造函数)来初始化的,函数的调用者得到的也是函数返回值的拷贝。为避免这种潜在的昂贵的开销,就不要通过值来传递对象,而要通过引用。通过引用来传递参数还有另外一个优点:它避免了... 阅读全文
posted @ 2014-08-16 13:38 合唱团abc 阅读(392) 评论(0) 推荐(0)
摘要:对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const,还有,两者都不指定为const: 声明迭代器为const表示这个迭代器不得指向不同的东西,但它所指的东西的值是可以改变的,如果希望迭代器所指的东西不可被改动,可以使用const_iterato 阅读全文
posted @ 2014-08-15 13:17 合唱团abc 阅读(217) 评论(0) 推荐(0)
摘要:成员函数和非成员函数最大的区别在于成员函数可以是虚拟的而非成员函数不行。所以,如果有个函数必须进行动态绑定(见条款38),就要采用虚拟函数,而虚拟函数必定是某个类的成员函数。如果函数不必是虚拟的,情况就稍微复杂一点。看下面表示有理数的一个类:class rational {public: rati... 阅读全文
posted @ 2014-08-14 13:24 合唱团abc 阅读(424) 评论(0) 推荐(0)
摘要:在赋值运算符中要特别注意可能出现别名的情况,其理由基于两点。其中之一是效率。如果可以在赋值运算符函数体的首部检测到是给自己赋值,就可以立即返回,从而可以节省大量的工作,否则必须去实现整个赋值操作。另一个更重要的原因是保证正确性。一个赋值运算符必须首先释放掉一个对象的资源(去掉旧值),然后根据新值分配... 阅读全文
posted @ 2014-08-11 14:13 合唱团abc 阅读(625) 评论(0) 推荐(1)
摘要:当涉及到继承时,派生类的赋值运算符也必须处理它的基类成员的赋值!否则,当派生类对象向另一个派生类对象赋值时,只有派生类部分赋值了。看看下面:class base {public: base(int initialvalue = 0): x(initialvalue) {}private: int... 阅读全文
posted @ 2014-08-11 14:05 合唱团abc 阅读(307) 评论(0) 推荐(0)
摘要:c++程序员经常犯的一个错误是让operator=返回void,这好象没什么不合理的,但它妨碍了连续(链式)赋值操作,所以不要这样做。一般情况下几乎总要遵循operator=输入和返回的都是类对象的引用的原则,然而有时候需要重载operator=使它能够接受不同类型的参数。例如,标准string类型... 阅读全文
posted @ 2014-08-11 13:40 合唱团abc 阅读(728) 评论(0) 推荐(0)
摘要:templateclass array {public: array(int lowbound, int highbound); ...private: vector data; // 数组数据存储在vector对象中 ... 阅读全文
posted @ 2014-08-11 13:09 合唱团abc 阅读(403) 评论(0) 推荐(0)
摘要:看这样一个模板,它生成的类使得一个名字和一个t类型的对象的指针关联起来。 在写namedptr构造函数时,必须将参数值传给相应的数据成员。有两种方法来实现。第一种方法是使用成员初始化列表: 第二种方法是在构造函数体内赋值: 从纯实际应用的角度来看,有些情况下必须用初始化。特别是const和引用数据成 阅读全文
posted @ 2014-08-09 15:51 合唱团abc 阅读(724) 评论(0) 推荐(0)
摘要:看下面一个表示string对象的类:// 一个很简单的string类class string {public: string(const char *value); ~string(); ... // 没有拷贝构造函数和operator=pr... 阅读全文
posted @ 2014-08-09 15:34 合唱团abc 阅读(492) 评论(1) 推荐(0)
摘要:为什么有必要写自己的operator new和operator delete?答案通常是:为了效率。缺省的operator new和operator delete具有非常好的通用性,它的这种灵活性也使得在某些特定的场合下,可以进一步改善它的性能。尤其在那些需要动态分配大量的但很小的对象的应用程序里,... 阅读全文
posted @ 2014-08-07 14:49 合唱团abc 阅读(473) 评论(1) 推荐(0)
摘要:因为内部范围声明的名称会隐藏掉外部范围的相同的名称,所以对于分别在类的内部和全局声明的两个相同名字的函数f来说,类的成员函数会隐藏掉全局函数class x {public: void f(); // operator new的参数指定一个 // new-hander(new的出错处理)函数 ... 阅读全文
posted @ 2014-08-06 15:01 合唱团abc 阅读(212) 评论(0) 推荐(0)
摘要:自己重写operator new时(条款10解释了为什么有时要重写它),很重要的一点是函数提供的行为要和系统缺省的operator new一致。实际做起来也就是:要有正确的返回值;可用内存不够时要调用出错处理函数(见条款7);处理好0字节内存请求的情况。此外,还要避免不小心隐藏了标准形式的new,不... 阅读全文
posted @ 2014-08-06 14:49 合唱团abc 阅读(417) 评论(1) 推荐(0)
摘要:string *stringarray = new string[100];...delete stringarray;上述程序的运行情况将是不可预测的。至少,stringarray指向的100个string对象中的99个不会被正确地摧毁,因为他们的析构函数永远不会被调用。用new的时候会发生两件事... 阅读全文
posted @ 2014-08-05 14:17 合唱团abc 阅读(232) 评论(0) 推荐(0)
摘要:malloc和free(及其变体)会产生问题的原因在于它们太简单:他们不知道构造函数和析构函数。假设用两种方法给一个包含10个string对象的数组分配空间,一个用malloc,另一个用new:string *stringarray1 =static_cast(malloc(10 * sizeof(... 阅读全文
posted @ 2014-08-04 14:24 合唱团abc 阅读(226) 评论(0) 推荐(0)
摘要:编译器会永远也看不到ASPECT_RATIO这个符号名,因为在源码进入编译器之前,它会被预处理程序去掉,于是ASPECT_RATIO不会加入到符号列表中。如果涉及到这个常量的代码在编译时报错,就会很令人费解,因为报错信息指的是1.653,而不是ASPECT_RATIO。 解决这个问题的方案很简单:不 阅读全文
posted @ 2014-08-04 14:05 合唱团abc 阅读(238) 评论(0) 推荐(0)