C++ primer plus 学习笔记

加油!2014-2-8

1、使用cout输出一个字符串,或者用strlen获取一个字符串的长度,都是找到该地址开始后面的第一个’\0’为止,对于普通的字符数组,甚至其他类型的数组,是不能使用该方法进行操作的。总之,如果给cout提供一个字符的地址,则它将从该字符开始打印,直到遇到空字符为止。

 

2、一定要在对指针使用解除引用运算符(*)之前,将指针初始化为一个确定的、适当的地址。

int * fellow;

*fellow = 233;//将233放到一个未知的地方

 

3、使用delete的关键在于,将它用于new分配的内存,即用于new的地址,而不是new的指针本身。

int * ps = new int;

int * pq = ps;

delete pq;//使用第二个指针来释放该内存,不能重复释放,如再次调用delete ps。

 

4、不能使用sizeof运算符来确定动态分配的数组包含的字节数。

int *a = newint[3];

cout <<sizeof(a) << endl; //输出4,即地址的字节数

在参数传递的时候也是如此,为了将数组类型和数组长度告诉处理函数,应使用如下形式:

void fillArray(int arr[], int size);

不能在函数中使用sizeof arr的原因:指针本身并没有指出数组的长度。

 

5、使用new创建动态数组,要用delete[]来释放,注意,修改指针位置后,释放前要将指针返回原来的位置。

   int *nums = new int[3];

   nums[0] = 0;

   nums[1] = 1;

   nums[2] = 2;

 

   nums = nums + 1;

   delete [] nums;//无效

 

    int*nums1 = nums - 1;

   delete [] nums1;

 

6、将指针变量加1后,其增加的值等于指向的类型占用的字节数。

注:数组的地址


还可以将一个指针减去另一个指针,获得两个指针的差,仅当两个指针指向同一个数组时,得到两个元素的间隔

 

7、在很多情况下,可以使用相同方式使用指针和数组名。区别之一是,可以修改指针的值,而数组名是常量。另一个区别是,对数组应用sizeof运算符得到的是数组的长度,而对指针应用sizeof得到的是指针的长度,即使指针指向的是一个数组。

 

8、在将字符串读入程序时,应使用已分配的内存地址。该地址可以是数组名,也可以是使用new初始化过的指针。

 

加油!2014-2-9

 

1、在for循环中,对于内置类型,采用++i与i++不会有差别,但对于用户定义的类型,如果有用户定义的递增和递减运算符,则前缀格式的效率更高。因为用户这样定义前缀函数:将值加1,然后返回结果;但后缀版本首先复制一个副本,将其加1,然后将复制的副本返回。

 

2、string类重载了==和!=运算符,条件是,至少有一个操作数为string对象,另一个操作数可以使string对象,也可以是C-风格字符串(一个以’\0’结尾的字符数组或者””括起来的字符串常量)。而两个C-风格字符串不能直接使用==或者!=。

 

3、C++中为类型创建别名有两种方法:

1)使用#define,如:

#define BYTE char//BYTE成为char的别名

2)使用typedef

typedef char byte;

就像用char声明一个变量一样,只是在前面加上typedef关键字。

不过,声明一系列变量时,不能用#define,如

#define FLOAT_POINTER float *;

fLOAT_POINTER pa,pb;

编译器会该声明转换为:

float * pa,pb;

这样,pb并不是指针,而是值。使用typedef则不会有这样的问题。

 

加油!2014-2-10

 

1、

2、读取文件是,good()方法指出最后一次读取输入的操作是否成功,这一点至关重要。这意味着应该在读取输入后立刻执行这种检测。为此,一种标准的方法是,在循环之前(首次执行循环测试前)放置一条输入语句,并在循环的末尾(下次执行循环测试之前)放置另一条输入语句。

//standard file-reading loop design

inFile >> value;  //get first value

while(inFile.good())  //while input good and not at EOF

{

         //loopbody

         inFile>> value; //get next value

}

或者,

while(inFile >> value)

{

         //loopbody

}

 

加油!2014-2-12

1、除非函数的目的就是修改传递给它的数据,否则应该避免发生这种情况。使用普通参数时,这种保护将自动实现,这是由于C++按值传递数据,而且函数使用数据的副本。然而,接受数组名的函数将使用原始数据,为防止无意中修改数据的内容,可以在声明形参时使用const关键字。

 

2、如果数据类型本身不是指针,则可以将const数据和非const数据的地址赋给指向const的指针,但只能将非const数据的地址赋给非指向const的指针。

 

3、指向const的指针和const指针

1)指向const的指针表示的是指针指向的值(可以是无const修饰的普通变量)不能通过”*指针”的方式修改

int sloth = 3;

const int * ps = &sloth;

此时,不能使用*ps += 1或 cin >> *pt的方式来修改值,不过可以通过sloth本身来修改。

但是ps指针本身是可以被修改的

int number = 4;

ps = &number;

2)const指针

无法修改指针的值

int * const finger = &sloth;

此时,finger只能指向sloth,但允许使用finger来修改sloth的值。

 

加油!2014-2-13

1、const只能修饰指向基本类型的指针,不能修饰指针的指针。

 

加油!2014-2-14

1、必须在声明引用变量时进行初始化。简而言之,可以通过初始化声明来设置引用,但不能通过赋值来设置。

引用更接近const指针,必须在创建的时候进行初始化,一旦与某个变量关联起来,就将一直效忠于它。也就是说:

         int& rodents = rats;

实际上是下述代码的伪装表示:

         intconst *pr = &rats;

 

2、如果函数调用的参数不是左值(不是左值例如字面值)或与相应的const引用参数的类型不匹配,则C++将创建类型正确的匿名变量,将函数调用的参数的值传递给匿名变量,并让参数来引用该变量。

如果接受引用参数的函数的意图是修改作为参数传递的变量,则创建临时变量将阻止这种意图的实现。解决方法是,禁止创建临时变量,现在C++标准正是这样的。

 

3、将引用参数声明为常量数据的引用的理由有三个:

1)使用const可以避免无意中修改数据的编程错误;

2)使用const使函数能够处理const和非const实参,否则将只能接受非const数据;

3)使用const引用使函数能够正确生成并使用临时变量。

因此,应尽量将引用声明为const。

 

4、返回引用时最重要的一点是,应避免返回函数终止时不再存在的内存单元引用。应避免编写下面的代码:

const free_throws & clone2(free_throws& ft)

{

         free_throwsnewguy;

         newguy= ft;

         returnnewguy;

}

该函数返回一个指向临时变量(newguy)的引用,函数运行完毕后它将不复存在。同样,也应该避免返回指向临时变量的指针。

为避免这个问题,最简单的方法是,返回一个作为参数传递给函数的引用。

另一种方法是用new来分配新的存储空间。

const free_throws & clone(free_throws& ft)

{

         free_throws*pt;

         *pt= ft;

         return*pt;

}

这种方法存在一个问题:在不再需要new分配的内存时,应使用delete来释放,容易被遗忘。

加油!2014-2-19

1.默认参数的使用:

char * left(const char * str, int n = 1);

默认参数要放在右边。

2.参数传递的指导原则:

对于使用传递的值而不做修改的函数:

1)如果数据对象很小,如内置数据类型或小型结构,则按值传递。

2)如果数据对象是数组,则使用指针,因为这是唯一的选择,并将指针声明为const的指针。

3)如果数据对象是较大的结构,则使用指针或者引用,提高程序运行效率。这样可以节省复制结构所需的时间和空间。

4)如果数据对象是类对象,则使用const引用,类设计的语义常常要求使用引用。、


对于修改调用函数中数据的函数:

1)如果数据对象是内置数据类型,则使用指针。

2)如果数据对象是数组,则只能使用指针。

3)如果数据对象是结构,则使用指针或引用。

4)如果数据对象是类对象,则使用引用。


加油!2014-2-20

1.头文件中应该包含的内容

  • 函数原型
  • 使用#define或const定义的符号常量
  • 结构声明
  • 类声明
  • 模板声明
  • 内联函数

2.

3.外部变量的使用

C++提供了两种变量声明。一种是定义声明,或简称定义,它给变量分配存储空间;一种是引用声明,或简称声明,它不给变量分配存储空间,因为它引用已有的变量。

引用声明使用extern,且不进行初始化。如果要在多个文件中使用外部变量,只需要在一个文件中包含该变量的定义,但在使用该变量的其他所有文件中,都必须使用关键字extern声明它。

4.局部静态变量的使用

如果在函数中声明了局部静态变量,则多次调用该函数时,访问的是同一个变量,程序开始运行时初始化一次,以后便一直存在。

#include <iostream>

using namespace std;

const int ArSize = 10;

void strcount(const char* str);

int main()
{
    char input[ArSize];
    char next;

    cout << "Enter a line:\n";
    cin.get(input,ArSize);

    while(cin)
    {
        cin.get(next);
        while(next != '\n')
        {
            cin.get(next);
        }
        strcount(input);

        cout << "Enter next line (empty line to quit):\n";
        cin.get(input,ArSize);

    }
    cout << "Bye.\n";


    return 0;
}

void strcount(const char* str)
{
    static int total = 0;//局部静态变量
    int count = 0;

    cout << "\"" << str << "\" contains ";

    while(*str++)
    {
        count ++;
    }

    total += count;

    cout << count << " characters \n";
    cout << total << " characters total\n";


}


其中total为局部静态变量,可以计算多次调用该函数时,总的次数。


加油!2014-2-25

1.类设计尽可能将公有接口与实现细节分开。公有接口表示设计的抽象组件,将实现细节放在一起并与抽象分开被称为封装。数据隐藏(将数据放在类的私有部分)是一种封装,将实现细节放在私有部分中,也是一种封装。封装的另一个定义是,将类函数定义和类声明放在不同的文件中。


2.C++对结构进行了扩展,使之具有与类相同的特性。他们之间唯一的区别是,结构的默认访问权限是public,而类为private。


3.所创建的每个新对象都有自己的存储空间,用于存储其内部变量和类成员;但同一个类的所有对象共享同一组类方法,即每种方法只有一个副本。


4.不要将类成员名称用作构造函数的参数名,为避免混乱,通常在数据成员中使用m_前缀或者后缀_。


5.C++提供了两种使用构造函数的方法。

    第一种是显示地调用构造函数:Stock food = Stock("aaa",250,1,25);

    另一种方式是隐式地调用构造函数:Stock garment("bbb",123,1.22);

    将构造函数与new一起使用的方法:Stock *pstock = new Stock("ccc",142,1.34);此时创建了一个Stock对象,对象没有名字,但是可以用pstock指针来管理该对象。


6.默认构造函数是在未提供显示初始值时,用来创建对象的构造函数。也就是说,它是用于下面这种声明的构造函数:Stock stock;

在设计类时,通常应提供对所有类成员做隐式初始化的默认构造函数。隐式的调用默认构造函数时,不要使用圆括号。


7.只要类方法不修改调用对象,就应该将其声明为const。

声明时:void show() const;

定义时:void Stock::show() const


8.接受一个参数的构造函数允许使用赋值语句将对象初始化为一个值。即如果构造函数只有一个参数,则将对象初始化为一个与参数类型相同的值时,该构造函数将被调用。


9.如果构造函数使用了new,则必须提供使用delete的析构函数。


10.this指针指向用来调用成员函数的对象(this被作为隐式参数发送给对象)。一般来说,所有的类方法都将this指针设置为调用它的对象的地址。如果方法需要引用这个调用对象,则可以使用*this。在函数的括号后面使用const限定符将this指针限定为const,这样,不能使用this来修改对象的值。


加油!2014-2-27

1.对于函数模板,声明和定义多要放在头文件中,不能像普通函数那样,声明放在头文件,定义放在另一个文件。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值