如何阅读 effective c++

作者&投稿:雀和 (若有异议请与网页底部的电邮联系)
如何阅读effective c++~

他们讲的都是C++的编程技巧和注意事项,很多都是自己平时不太注意但又很重要的内容,绝对经典。More Effective C++比Effective C++略深,但总体讲的是不同的内容。这个系列还出了第三版,叫Effective C++ Style,好像还没有中译版,我看了下,新内容要少些,可能看同样问题角度不同。

如果你要C++进阶,Effective和More Effective都是必不可少的书。Effective讲的很基础,建议先仔细看完。

另外我的书还有《深入探索C++对象模型》,讲的是C++内部的机制。另外学习C++,除了语言本身之外,操作系统也要学好,还有编译原理,这样才能透彻地理解C++。

应用方面也可以学下,比如较容易学习的MFC。

初学不宜,专门研究C++的理论要精读。类似于汉语的说文解字,一般人不需要!另外东西方文化的差异也造成此时中的一些内容不适合中国。

  转载 记得前段时间又一次拿起《Effective C++》的时候,有种豁然开朗的感觉,所以翻出了我第一遍读时做的笔记。只做参考以及查阅之用。如有需要请参阅《Effective C++》书本。 by shenzi/2010.5.17
  一.让自己习惯C++

  条款01:视C++为一个语言联邦
为了更好的理解C++,我们将C++分解为四个主要次语言:

  C。说到底C++仍是以C为基础。区块,语句,预处理器,内置数据类型,数组,指针统统来自C。
  Object-Oreinted C++。这一部分是面向对象设计之古典守则在C++上的最直接实施。类,封装,继承,多态,virtual函数等等...
  Template C++。这是C++泛型编程部分。
  STL。STL是个template程序库。容器(containers),迭代器(iterators),算法(algorithms)以及函数对象(function objects)...
  请记住:

  这四个次语言,当你从某个次语言切换到另一个,导致高效编程守则要求你改变策略。C++高效编程守则视状况而变化,取决于你使用C++的哪一部分。
  条款02:尽量以const,enum,inline替换#define
这个条款或许可以改为“宁可 以编译器替换预处理器”。即尽量少用预处理。

  编译过程:.c文件--预处理-->.i文件--编译-->.o文件--链接-->bin文件
  预处理过程扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器。检查包含预处理指令的语句和宏定义,并对源代码进行相应的转换。预处理过程还会删除程序中的注释和多余的空白字符。可见预处理过程先于编译器对源代码进行处理。预处理指令是以#号开头的代码行。
  例:#define ASPECT_RATIO 1.653
  记号名称ASPECT_RATIO也许从未被编译器看见,也许在编译器开始处理源代码之前它就被预处理器移走了。即编译源代码时ASPECT_RATIO已被1.653取代。ASPECT_RATIO可能并未进入记号表(symbol table)。
  替换:const double AspectRatio = 1.653;
  好处应该有:多了类型检查,因为#define 只是单纯的替换,而这种替换在目标码中可能出现多份1.653;改用常量绝不会出现相同情况。

  常量替换#define两点注意:

  定义常量指针:
  const char *authorName = “Shenzi”;
cosnt std::string authorName("Shenzi");

  类专属常量:
  static const int NumTurns = 5;//static 静态常量 所有的对象只有一份拷贝。
万一你编译器不允许“static整数型class常量”完成“in calss初值设定”(即在类的声明中设定静态整形的初值),我们可以通过枚举类型予以补偿:
enum { NumTurns = 5 };
*取一个const的地址是合法的,但取一个enum的地址就不合法,而取一个#define的地址通常也不合法。如果你不想让别人获取一个pointer或reference指向你的某个整数常量,enum可以帮助你实现这个约束。
例:#define CALL_WITH_MAX(a,b) f((a) > (b)) ? (a) : (b))
宏看起来像函数,但不会招致函数调用带来的额外开销,而是一种简单的替换。
替换:
template<typename T>
inline void callWithMax(cosnt T &a, cosnt T &b)
{
f(a > b ? a : b);
}
callWithMax是个真正的函数,它遵循作用于和访问规则。
请记住:

  对于单纯常量,最好以const对象或enums替换#defines;
  对于形似函数的宏,最好改用inline函数替换#defines。

  条款03:尽可能使用const
const允许你告诉编译器和其他程序员某值应保持不变,只要“某值”确实是不该被改变的,那就该确实说出来。
关键字const多才多艺:
例:
char greeting[] = "Hello";
char *p = greeting; //指针p及所指的字符串都可改变;
const char *p = greeting; //指针p本身可以改变,如p = &Anyother;p所指的字符串不可改变;
char * cosnt p = greeting; //指针p不可改变,所指对象可改变;
const char * const p = greeting; //指针p及所致对象都不可改变;
说明:

  如果关键字const出现在星号左边,表示被指物事常量。const char *p和char const *p两种写法意义一样,都说明所致对象为常量;
  如果关键字const出现在星号右边,表示指针自身是常量。
  STL例子:
const std::vector<int>::interator iter = vec.begin();//作用像T *const, ++iter 错误:iter是const
std::vector<int>::const_iterator cIter = vec.begin();//作用像const T*,*cIter = 10 错误:*cIter是const
以下几点注意:
  令函数返回一个常量值,往往可以降低因客户错误而造成的意外,而不至于放弃安全性和高效性。
  例:const Rational operator* (const Rational &lhs, cosnt Rational &rhs);

  const成员函数使class接口比较容易被理解,它们使“操作const对象”称为可能;
  说明:声明为const的成员函数,不可改变non-static成员变量,在成员变量声明之前添加mutable可让其在const成员函数中可被改变。
const_cast<char &>(static_cast<const TextBlock &>(*this))[position];
//static_cast 将TextBlock &转为const TextBlock &;
//const_cast将返回值去掉const约束;
请记住:

  将某些东西声明为const可帮助编译器侦测出错误用法。const可被施加于任何作用域内的对象、函数参数、函数返回类型、成员函数本体;
  编译器强制实施bitwise constness,但你编写程序时应该使用“概念上的车辆”(conceptual constness);
  当cosnt和non-const成员函数有着实质等价的实现时,令non-const版本调用const版本可避免代码重复。
  条款04:确定对象被使用前已先被初始化
永远在使用对象之前先将它初始化。对于无任何成员的内置类型,你必须手工完成此事。至于内置类型以外的任何其它东西,初始化责任落在构造函数身上,确保每一个构造函数都将对象的每一个成员初始化。
赋值和初始化:
C++规定,对象的成员变量的初始化动作发生在进入构造函数本体之前。所以应将成员变量的初始化置于构造函数的初始化列表中。
ABEntry::ABEntry(const std::string& name, const std::string& address,
const std::list<PhoneNumber>& phones)
{
theName = name; //这些都是赋值,而非初始化
theAddress = address; //这些成员变量在进入函数体之前已调用默认构造函数,接着又调用赋值函数,
thePhones = phones; //即要经过两次的函数调用。
numTimesConsulted = 0;
}

ABEntry::ABEntry(const std::string& name, const std::string& address,
const std::list<PhoneNumber>& phones)
: theName(name), //这些才是初始化
theAddress(address), //这些成员变量只用相应的值进行拷贝构造函数,所以通常效率更高。
thePhones(phones),
numTimesConsulted(0)
{ }
所以,对于非内置类型变量的初始化应在初始化列表中完成,以提高效率。而对于内置类型对象,如numTimesConsulted(int),其初始化和赋值的成本相同,但为了一致性最好也通过成员初始化表来初始化。如果成员变量时const或reference,它们就一定需要初值,不能被赋值。
C++有着十分固定的“成员初始化次序”。基类总是在派生类之前被初始化,而类的成员变量总是以其说明次序被初始化。所以:当在成员初始化列表中列各成员时,最好总是以其声明次序为次序。
请记住:

  为内置对象进行手工初始化,因为C++不保证初始化它们;
  构造函数最好使用成员初始化列表,而不要在构造函数本体内使用赋值操作。初始化列表列出的成员变量,其排列次序应该和它们在类中的声明次序相同;
  为免除“跨编译单元之初始化次序”问题,请以local static对象替换non-local static对象。
  二.构造/析构/赋值运算
几乎你写的每个类都会有一或多个构造函数、一个析构函数、一个拷贝赋值操作符。如果这些函数犯错,会导致深远且令人不愉快的后果,遍及整个类。所以确保它们行为正确时生死攸关的大事。

  条款05:了解C++默默编写并调用哪些函数
如果你自己美声明,编译器就会为类声明(编译器版本的)一个拷贝构造函数,一个拷贝赋值操作符和一个析构函数。此外如果你没有声明任何构造函数,编译器也会成为你声明一个默认构造函数。所有这些函数都是public且inline。
惟有当这些函数被需要(被调用),它们才会被编译器创建出来。即有需求,编译器才会创建它们。
默认构造函数和析构函数主要是给编译器一个地方用来放置“藏身幕后”的代码,像是调用基类和非静态成员变量的构造函数和析构函数(要不然它们该在哪里被调用呢??)。
注意:编译器产生的析构函数是个non-virtual,除非这个类的基类自身声明有virtual析构函数。
至于拷贝构造函数和拷贝赋值操作符,编译器创建的版本只是单纯地将来源对象的每一个非静态成员变量拷贝到目标对象。
如一个类声明了一个构造函数(无论有没参数),编译器就不再为它创建默认构造函数。
编译器生成的拷贝赋值操作符:对于成员变量中有指针,引用,常量类型,我们都应考虑建立自己“合适”的拷贝赋值操作符。因为指向同块内存的指针是个潜在危险,引用不可改变,常量不可改变。
请记住:

  编译器可以暗自为类创建默认构造函数、拷贝构造函数、拷贝赋值操作符,以及析构函数。
  条款06:若不想使用编译器自动生成的函数,就该明确拒绝
通常如果你不希望类支持某一特定技能,只要不说明对应函数就是了。但这个策略对拷贝构造函数和拷贝赋值操作符却不起作用。因为编译器会“自作多情”的声明它们,并在需要的时候调用它们。
由于编译器产生的函数都是public类型,因此可以将拷贝构造函数或拷贝赋值操作符声明为private。通过这个小“伎俩”可以阻止人们在外部调用它,但是类中的成员函数和友元函数还是可以调用private函数。解决方法可能是在一个专门为了阻止拷贝动作而设计的基类。(Boost提供的那个类名为noncopyable)。
请记住:

  为驳回编译器自动(暗自)提供的机能,可将相应的成员函数声明为private并且不予实现。使用像noncopyable这样的基类也是一种做法。
  条款07:为多态基类声明virtual析构函数
当基类的指针指向派生类的对象的时候,当我们使用完,对其调用delete的时候,其结果将是未有定义——基类成分通常会被销毁,而派生类的充分可能还留在堆里。这可是形成资源泄漏、败坏之数据结构、在调试器上消费许多时间。
消除以上问题的做法很简单:给基类一个virtual析构函数。此后删除派生类对象就会如你想要的那般。
任何类只要带有virtual函数都几乎确定应该也有一个virtual析构函数。
如果一个类不含virtual函数,通常表示它并不意图被用做一个基类,当类不企图被当做基类的时候,令其析构函数为virtual往往是个馊主意。因为实现virtual函数,需要额外的开销(指向虚函数表的指针vptr)。

  STL容器都不带virtual析构函数,所以最好别派生它们。

  请记住:

  带有多态性质的基类应该声明一个virtual析构函数。如果一个类带有任何virtual函数,它就应该拥有一个virtual析构函数。
  一个类的设计目的不是作为基类使用,或不是为了具备多态性,就不该声明virtual析构函数。

转载 记得前段时间又一次拿起《Effective C++》的时候,有种豁然开朗的感觉,所以翻出了我第一遍读时做的笔记。只做参考以及查阅之用。如有需要请参阅《Effective C++》书本。 by shenzi/2010.5.17
一.让自己习惯C++

条款01:视C++为一个语言联邦
为了更好的理解C++,我们将C++分解为四个主要次语言:

C。说到底C++仍是以C为基础。区块,语句,预处理器,内置数据类型,数组,指针统统来自C。
Object-Oreinted C++。这一部分是面向对象设计之古典守则在C++上的最直接实施。类,封装,继承,多态,virtual函数等等...
Template C++。这是C++泛型编程部分。
STL。STL是个template程序库。容器(containers),迭代器(iterators),算法(algorithms)以及函数对象(function objects)...
请记住:

这四个次语言,当你从某个次语言切换到另一个,导致高效编程守则要求你改变策略。C++高效编程守则视状况而变化,取决于你使用C++的哪一部分。
条款02:尽量以const,enum,inline替换#define
这个条款或许可以改为“宁可 以编译器替换预处理器”。即尽量少用预处理。

编译过程:.c文件--预处理-->.i文件--编译-->.o文件--链接-->bin文件
预处理过程扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器。检查包含预处理指令的语句和宏定义,并对源代码进行相应的转换。预处理过程还会删除程序中的注释和多余的空白字符。可见预处理过程先于编译器对源代码进行处理。预处理指令是以#号开头的代码行。
例:#define ASPECT_RATIO 1.653
记号名称ASPECT_RATIO也许从未被编译器看见,也许在编译器开始处理源代码之前它就被预处理器移走了。即编译源代码时ASPECT_RATIO已被1.653取代。ASPECT_RATIO可能并未进入记号表(symbol table)。
替换:const double AspectRatio = 1.653;
好处应该有:多了类型检查,因为#define 只是单纯的替换,而这种替换在目标码中可能出现多份1.653;改用常量绝不会出现相同情况。

常量替换#define两点注意:

定义常量指针:
const char *authorName = “Shenzi”;
cosnt std::string authorName("Shenzi");

类专属常量:
static const int NumTurns = 5;//static 静态常量 所有的对象只有一份拷贝。
万一你编译器不允许“static整数型class常量”完成“in calss初值设定”(即在类的声明中设定静态整形的初值),我们可以通过枚举类型予以补偿:
enum { NumTurns = 5 };
*取一个const的地址是合法的,但取一个enum的地址就不合法,而取一个#define的地址通常也不合法。如果你不想让别人获取一个pointer或reference指向你的某个整数常量,enum可以帮助你实现这个约束。
例:#define CALL_WITH_MAX(a,b) f((a) > (b)) ? (a) : (b))
宏看起来像函数,但不会招致函数调用带来的额外开销,而是一种简单的替换。
替换:
template<typename T>
inline void callWithMax(cosnt T &a, cosnt T &b)
{
f(a > b ? a : b);
}
callWithMax是个真正的函数,它遵循作用于和访问规则。
请记住:

对于单纯常量,最好以const对象或enums替换#defines;
对于形似函数的宏,最好改用inline函数替换#defines。

条款03:尽可能使用const
const允许你告诉编译器和其他程序员某值应保持不变,只要“某值”确实是不该被改变的,那就该确实说出来。
关键字const多才多艺:
例:
char greeting[] = "Hello";
char *p = greeting; //指针p及所指的字符串都可改变;
const char *p = greeting; //指针p本身可以改变,如p = &Anyother;p所指的字符串不可改变;
char * cosnt p = greeting; //指针p不可改变,所指对象可改变;
const char * const p = greeting; //指针p及所致对象都不可改变;
说明:

如果关键字const出现在星号左边,表示被指物事常量。const char *p和char const *p两种写法意义一样,都说明所致对象为常量;
如果关键字const出现在星号右边,表示指针自身是常量。
STL例子:
const std::vector<int>::interator iter = vec.begin();//作用像T *const, ++iter 错误:iter是const
std::vector<int>::const_iterator cIter = vec.begin();//作用像const T*,*cIter = 10 错误:*cIter是const
以下几点注意:
令函数返回一个常量值,往往可以降低因客户错误而造成的意外,而不至于放弃安全性和高效性。
例:const Rational operator* (const Rational &lhs, cosnt Rational &rhs);

const成员函数使class接口比较容易被理解,它们使“操作const对象”称为可能;
说明:声明为const的成员函数,不可改变non-static成员变量,在成员变量声明之前添加mutable可让其在const成员函数中可被改变。
const_cast<char &>(static_cast<const TextBlock &>(*this))[position];
//static_cast 将TextBlock &转为const TextBlock &;
//const_cast将返回值去掉const约束;
请记住:

将某些东西声明为const可帮助编译器侦测出错误用法。const可被施加于任何作用域内的对象、函数参数、函数返回类型、成员函数本体;
编译器强制实施bitwise constness,但你编写程序时应该使用“概念上的车辆”(conceptual constness);
当cosnt和non-const成员函数有着实质等价的实现时,令non-const版本调用const版本可避免代码重复。
条款04:确定对象被使用前已先被初始化
永远在使用对象之前先将它初始化。对于无任何成员的内置类型,你必须手工完成此事。至于内置类型以外的任何其它东西,初始化责任落在构造函数身上,确保每一个构造函数都将对象的每一个成员初始化。
赋值和初始化:
C++规定,对象的成员变量的初始化动作发生在进入构造函数本体之前。所以应将成员变量的初始化置于构造函数的初始化列表中。
ABEntry::ABEntry(const std::string& name, const std::string& address,
const std::list<PhoneNumber>& phones)
{
theName = name; //这些都是赋值,而非初始化
theAddress = address; //这些成员变量在进入函数体之前已调用默认构造函数,接着又调用赋值函数,
thePhones = phones; //即要经过两次的函数调用。
numTimesConsulted = 0;
}

ABEntry::ABEntry(const std::string& name, const std::string& address,
const std::list<PhoneNumber>& phones)
: theName(name), //这些才是初始化
theAddress(address), //这些成员变量只用相应的值进行拷贝构造函数,所以通常效率更高。
thePhones(phones),
numTimesConsulted(0)
{ }
所以,对于非内置类型变量的初始化应在初始化列表中完成,以提高效率。而对于内置类型对象,如numTimesConsulted(int),其初始化和赋值的成本相同,但为了一致性最好也通过成员初始化表来初始化。如果成员变量时const或reference,它们就一定需要初值,不能被赋值。
C++有着十分固定的“成员初始化次序”。基类总是在派生类之前被初始化,而类的成员变量总是以其说明次序被初始化。所以:当在成员初始化列表中列各成员时,最好总是以其声明次序为次序。
请记住:

为内置对象进行手工初始化,因为C++不保证初始化它们;
构造函数最好使用成员初始化列表,而不要在构造函数本体内使用赋值操作。初始化列表列出的成员变量,其排列次序应该和它们在类中的声明次序相同;
为免除“跨编译单元之初始化次序”问题,请以local static对象替换non-local static对象。
二.构造/析构/赋值运算
几乎你写的每个类都会有一或多个构造函数、一个析构函数、一个拷贝赋值操作符。如果这些函数犯错,会导致深远且令人不愉快的后果,遍及整个类。所以确保它们行为正确时生死攸关的大事。

条款05:了解C++默默编写并调用哪些函数
如果你自己美声明,编译器就会为类声明(编译器版本的)一个拷贝构造函数,一个拷贝赋值操作符和一个析构函数。此外如果你没有声明任何构造函数,编译器也会成为你声明一个默认构造函数。所有这些函数都是public且inline。
惟有当这些函数被需要(被调用),它们才会被编译器创建出来。即有需求,编译器才会创建它们。
默认构造函数和析构函数主要是给编译器一个地方用来放置“藏身幕后”的代码,像是调用基类和非静态成员变量的构造函数和析构函数(要不然它们该在哪里被调用呢??)。
注意:编译器产生的析构函数是个non-virtual,除非这个类的基类自身声明有virtual析构函数。
至于拷贝构造函数和拷贝赋值操作符,编译器创建的版本只是单纯地将来源对象的每一个非静态成员变量拷贝到目标对象。
如一个类声明了一个构造函数(无论有没参数),编译器就不再为它创建默认构造函数。
编译器生成的拷贝赋值操作符:对于成员变量中有指针,引用,常量类型,我们都应考虑建立自己“合适”的拷贝赋值操作符。因为指向同块内存的指针是个潜在危险,引用不可改变,常量不可改变。
请记住:

编译器可以暗自为类创建默认构造函数、拷贝构造函数、拷贝赋值操作符,以及析构函数。
条款06:若不想使用编译器自动生成的函数,就该明确拒绝
通常如果你不希望类支持某一特定技能,只要不说明对应函数就是了。但这个策略对拷贝构造函数和拷贝赋值操作符却不起作用。因为编译器会“自作多情”的声明它们,并在需要的时候调用它们。
由于编译器产生的函数都是public类型,因此可以将拷贝构造函数或拷贝赋值操作符声明为private。通过这个小“伎俩”可以阻止人们在外部调用它,但是类中的成员函数和友元函数还是可以调用private函数。解决方法可能是在一个专门为了阻止拷贝动作而设计的基类。(Boost提供的那个类名为noncopyable)。
请记住:

为驳回编译器自动(暗自)提供的机能,可将相应的成员函数声明为private并且不予实现。使用像noncopyable这样的基类也是一种做法。
条款07:为多态基类声明virtual析构函数
当基类的指针指向派生类的对象的时候,当我们使用完,对其调用delete的时候,其结果将是未有定义——基类成分通常会被销毁,而派生类的充分可能还留在堆里。这可是形成资源泄漏、败坏之数据结构、在调试器上消费许多时间。
消除以上问题的做法很简单:给基类一个virtual析构函数。此后删除派生类对象就会如你想要的那般。
任何类只要带有virtual函数都几乎确定应该也有一个virtual析构函数。
如果一个类不含virtual函数,通常表示它并不意图被用做一个基类,当类不企图被当做基类的时候,令其析构函数为virtual往往是个馊主意。因为实现virtual函数,需要额外的开销(指向虚函数表的指针vptr)。

STL容器都不带virtual析构函数,所以最好别派生它们。

请记住:

带有多态性质的基类应该声明一个virtual析构函数。如果一个类带有任何virtual函数,它就应该拥有一个virtual析构函数。
一个类的设计目的不是作为基类使用,或不是为了具备多态性,就不该声明virtual析构函数。


建始县15672248740: 如何阅读effective c++ -
茆婵筋络: 他们讲的都是C++的编程技巧和注意事项,很多都是自己平时不太注意但又很重要的内容,绝对经典.More Effective C++比Effective C++略深,但总体讲的是不同的内容.这个系列还出了第三版,叫Effective C++ Style,好像还没有中译版,我...

建始县15672248740: 如何阅读 effective c++ -
茆婵筋络: 转载 记得前段时间又一次拿起《Effective C++》的时候,有种豁然开朗的感觉,所以翻出了我第一遍读时做的笔记.只做参考以及查阅之用.如有需要请参阅《Effective C++》书本. by shenzi/2010.5.17一.让自己习惯C++条款01:视C++为一...

建始县15672248740: 读effective c++却难理解,c++primer已经看过了. -
茆婵筋络: 说明你目前还停留在c++初学者的阶段,最多也就是入门级的.Effective C++一书中列出了很多改善C++代码的建议,以及很多注意事项,作为新手,哪怕是刚看完c++ primer入门的人,很多问题你都还没有遇到过,脑子里没有作者说的使用c++的那些困惑,当然很多地方你就不理解.还有就是很多C++的特性你都没有接触到,c++很庞大.不多说了,再多写c++的程序,多看看开源软件源代码,等遇到问题了再回到Effective C++中来,你会有所得 ...

建始县15672248740: 如何正确的通过 C++ Primer 学习 C++ -
茆婵筋络: 学习C++的话,看你目前的水平,我说一下从完全不懂到最后高手的专家推荐路线吧:1.《C++Primer》Lippman写的,经典中的经典,C++入门的宝典,读完这本书,基本语法过关,部分技巧掌握.2.《TheC++programminglanguage》C++的...

建始县15672248740: 这几本关于C++的书哪个好? -
茆婵筋络: 入门的话可以看一下强哥的书,不过等学完后还是看看老外的书,推荐C++primer,毕竟老外的书写得是好,有能力的话(没能力也要尝试着开始读,学计算机的老外的书是不得不看的)可以看英文原版,读起来更有意思

建始县15672248740: 自学C++应该用哪本书 -
茆婵筋络: C++ PRIMER 看完就入门了 《c/c++深层探索》:将内部机制的 《c++标准库》 C++ Standard Library C陷阱和缺陷:学c++无法忽略C,C++是C的超集,真正掌握C++必定会掌握c,所以这本书逃不掉."一定的C语言基础"这本书就很好理解了.这书会让你更加了解C.《C++ templates》:这本书讲的是c++模板.《c++编程惯用法》,《effective c++》,《c++规范编程》:这几个是C++进阶时候阅读的 《linker and loader》:讲解某一编译过程的,想成为高手这本书也逃不掉 ,或许你会想阅读《编译原理》.然后你就去找与你发展的方向相关的类库的相关手册吧.

建始县15672248740: C++怎么学 -
茆婵筋络: 虽说是抄的 ,但是我觉得很有用!!舍弃浮躁, 50条重要的C++学习建议1.把C++当成一门新的语言学习(和C没啥关系!真的); 2.看《Thinking In C++》,不要看《C++变成死相》(C++编程思想,翻译的非常差); 3.看《The C++ ...

建始县15672248740: 这几本C++的书比较怎么样 -
茆婵筋络: 一直看C++ primer(第4中文版),适合新手,算是最简单的一本了 送你一份读书清单 (一)语言入门: 《C++ Primer》 适合有丰富C经验,缺乏C++经验的.不过我个人一直认为此书带着过于强烈的C语言的痕迹,对于C++的学习未必是好事...

建始县15672248740: effective c++适合c++进阶吗?要有一定难度 -
茆婵筋络: 嗯,《Effecttive C++》确实一本C++进阶的读物.不过,它讨论的大多不是难度的问题,而是技术.如果LZ想要难度的话,可以考虑找些介绍结构、算法的书籍.

建始县15672248740: 什么C++入门书籍最好? -
茆婵筋络: C++Primer中文版(第4版).pdf effectiveC++简体中文.chm 如上两本,第一本主要讲语法和基础知识,第二本主要讲一些经验.

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网