C++PrimerPlus(笔记)

开始学习有一段时间了,还是做一些笔记吧,不像之前那样一章开一篇了,这本书所以的笔记都在里,就记一下这章该注意的东西。
感觉这样做笔记的话还是挺花费时间的,但是C++值得这么花时间。有一个好处就是为了把博客写好我不会囫囵吞枣地跳读了。不用着急吧,

1.预备知识 2.开始学习C++

C++简史和预备知识,不再累述。

3 处理数据

3.1 变量名

下面的代码会输出各种变量类型所占的字节数以及它的最大最小值。
值得注意的是头文件climits,里面包含了各个类型的最大最小值。

#include <iostream>
#include <cmath>
#include <climits>
int main()
{
    using namespace std;
    int n_int = INT_MAX;
    short n_shot = SHRT_MAX;
    long n_long = LONG_MAX;
    long long n_llong = LLONG_MAX;

    cout << "char:" << sizeof(char) << endl
    << "short:" << sizeof(short) << endl
    << "int:" << sizeof(int) << endl
    << "float:" << sizeof(float) << endl
    << "double:" << sizeof(double) << endl
    << "long:" << sizeof(long) << endl
    << "long long:" << sizeof(long long) << endl;

    cout << "Maximum values:" << endl;
    cout << "int:" << n_int << endl;
    cout << "short:" << n_shot << endl;
    cout << "long:" << n_long << endl;
    cout << "long long:" << n_llong << endl;

    return 0;
}

4 复合类型

4.2

cin.getline()

C++的新特性,但本人还是喜欢用fget(char *, int const len, FILE *)
读取20个字符到name中
cin.getline(name, 20)

4.3 string类简介

感觉string超级好用
位于名称空间std中,所以要用的时候可以using namespace std

跟char数组的不同是:它可以赋值

string a;
a = "abcde";

还可以拼接

string a = "abcde", b = "fghijk";
string c = a + b; //c = "abcdefghijk";

4.3.5 其他形式的字符串字面值

C++分别用前缀L, u, U表示wchar_t, char16_t, char32_t

wchar_t title[] = L"Hello World";
char16_t name[] = u"Felonia Ripova";
char32_t car[] = U"TOYOTA"
原始字符串

R"(字符串内容)";
在这里,字符串中可以包含双引号""
如果要包含 "(呢?
那可以这样
cout << R"+*(字符串内容)+*"
这里,以"+*(开始字符串内容,以)+*”结束字符串内容,这样子如果字符串中含有"(就不会被读取。

4.4 4.5结构体,共用体

跟C语言里的差别不大

4.6枚举
enum color = {red, orage, yellow};
enum bigstep = {zero, null = 0, one, two};
// 如果不特别赋值,第一个元素等于0,之后每一个元素比前一个元素大1
// 也就是说,zero = 0, null = 0, one = 1, two = 2

说实话这个东西很少用

4.7指针和自由储存空间

用new 来分配空间,delete来释放内存

int *p;
p = new int;
delete p;

int *pd;
pd = new int [10];
delete [] pd 

new与delete成对,当new了数组时,delete要加方括号,即delete [] pd

5 循环和关系表达式 6分支语句和逻辑运算符

与C语言相同,不再累述
(C++11有点更新的,抽空更一下这部分)

7 函数——C++的编程模块

与第八章一起记

8 函数探幽

还是跟C语言差不多,有一点不同就是增加了引用变量,引用符号为&,就是传过去的参数可以直接被函数访问和修改,类似于之前的指针。
以Swap函数举例

#include <iostream>
using namespace std;
void Swap(int &a, int &b)
{
    int t;
    t = a;
    a = b;
    b = t;
}
int main()
{
    int a, b;
    a = 3;
    b = 5;
    Swap(a, b);
    cout << a << " " << b << endl;

    return 0;
}

- 如果不希望参数被改变的话,定义函数的时候就加上const

返回结构的引用

正常函数的返回值是一个临时变量,然后赋值给承接它的左值。但是如果返回一个引用,则直接赋值,效率会高一点

#include <cstdio>
#include <iostream>
using namespace std;

struct book 
{
    int num;
    int price;
};

book & add(book &one, book &two)
{
    one.num += two.num;
    return one;

    //better to return a reference that was declare in main function
}
int main()
{
    book one = {123, 456};
    book two = {100, 0};
    book three = add(one, two);
    printf ("%d %d", three.num, three.price);
}

8.3 默认参数

简单说就是,定义一个函数,函数里有形参,可以给一些参数定义默认值,当调用函数的时候,如果不给已经定义默认值的参数赋值,则为默认值。

#include <iostream>
const int ArSize = 80;
char * left(const char * str, int n = 1);
int main()
{
    using namespace std;
    char sample[ArSize];
    cout << "Enter a string:\n";
    cin.get(sample, ArSize);
    char *ps = left(sample, 4);
    cout << ps << endl;
    delete [] ps;
    ps = left(sample);
    cout << ps << endl;
    delete [] ps;
    return 0;
}

char * left(const char * str, int n)
{
    if (n < 0)
        n = 0;

    char * p = new char[n + 1];

    int i;
    for (i = 0; i < n && str[i]; i++)
        p[i] = str[i];
    while (i <= n)
    {
        p[i++] = '\0';
    }
    return p;
}

注:必须从右到左添加默认值,也就是说,如果某个参数为默认值,则它右边的参数必须都有默认值

8.4 重载

重载的意思就是,定义若干个名称相同但是形参不同的函数,编译器会根据形参的不同类型调用对应的函数

8.5 函数模板

目前为止最刷新我认知的一部分了
模板的一个作用就是,当你要使用不同类型的参数来实现同样的算法时,模板会帮助你少写构造函数。比如Swap(int a, int b),这是交换两个int类型的变量,但是你要交换double类型呢?或者char类型?如果没有模板的话,你要重新写两个函数。

下面是用了模板的Swap

#include <iostream>
#include <cstdio>
using namespace std;
template <typename T>
void Swap(T &a, T &b)
{
    T temp;
    temp = a;
    a = b;
    b = temp;
} 
int main()
{
    int i = 10;
    int j = 20;
    Swap(i, j);
    cout << i << " " << j << endl;

    double a = 30;
    double b = 40;
    Swap(a, b);
    cout << a << " " << b << endl;
    return 0;
}

重载的模板

并非所有的类型都使用相同的算法,所以模板也需要重载,就好像函数的重载一样。下面程序中的两个Swap一个是交换两个变量的,一个是交换两个数组的,明显这两个算法不一样。

#include <iostream>
template <typename T>
void Swap(T &a, T &b);

template <typename T>
void Swap(T *a, T *b, int n);

void Show(int a[]);
const int Lim = 8;
int main()
{
    using namespace std;
    int i = 10, j =20;
    cout << "i = " << i << ", j = " << j <<endl;
    cout << "Using compiler-genrate int swapper" << endl;
    Swap(i, j);
    cout << "Now, i = " << i << ", j = " << j << endl;

    int d1[Lim] = {3, 2, 4, 8, 12, 87, 40, 82};
    int d2[Lim] = {43, 12, 5, 76, 43, 62, 98, 10};
    cout << "d1 " << "d1" << endl;
    Show(d1);
    Show(d2);

    Swap(d1, d2, Lim);

    cout << "After swap :" << endl;
    Show(d1);
    Show(d2);
    return 0;
}


template <typename T>
void Swap(T &a, T &b)
{
    T temp;
    temp = a;
    a = b;
    b = temp;
}

template <typename T>
void Swap(T *a, T *b, int n)
{
    T temp;
    for (int i = 0; i < n; i++)
    {
        temp = a[i];
        a[i] = b[i];
        b[i] = temp;
    }
}

void Show(int a[])
{
    using namespace std;
    for (int i = 0; i < Lim; i++)
    {
        cout << a[i] << " ";
    }
    cout << endl;
}
显式具体化

用模板可以完成两个变量的交换了,但是如果是两个结构中的成员变量交换呢?那就需要再写一个具体的函数。
在下面的程序中是:template <> void Swap <job> (job &j1, job &j2);(重点,需要记一下)

#include <cstdio>
#include <iostream>
using namespace std;
template <typename T>
void Swap(T &a, T &b);
struct job
{
    char name[40];
    double salary;
    int floor;
};
template <> void Swap <job> (job &j1, job &j2);
void Show(job &j);

int main()
{
//  cout.precision(2);
//  cout.setf(ios::fixed, ios::floatfield);
    int i = 10, j = 20;
    Swap(i, j);
    cout << i << " " << j << endl;
    job sue = {"susan", 4300.2, 8};
    job sidney = {"Sidney", 78060.72, 9};
    Show(sue);
    Show(sidney);

    Swap(sue, sidney);

    Show(sue);
    Show(sidney);
    return 0;
}


template <typename T> // write this code when you use template everytime
void Swap(T &a, T &b)
{
    T temp;
    temp = a;
    a = b;
    b = temp;
}

template <> void Swap<job>(job &j1, job &j2)
{
    double t1;
    int t2;

    t1 = j1.salary;
    j1.salary = j2.salary;
    j2.salary = t1;

    t2 = j1.floor;
    j1.floor = j2.floor;
    j2.floor = t2;
}

void Show(job & j)
{
    cout << j.name << endl;
    cout << j.salary << endl;
    cout << j.floor << endl;
    cout <<endl;
} 

9 内存模型和名称空间

9.1 单独编译

将程序分为三部分:

头文件:包含结构声明和函数的原型。
源代码文件:定义结构和函数。
源代码文件:编写调用函数的代码。

9.2 存储持续性、作用域和链接性

持续性是指变量保留在内存中的时间。

  • 自动变量会随着代码块的执行结束而被释放掉,自动变量也就是通常声明的普通变量。int a; double b ;
  • 静态变量在整个程序执行过程中都存在,静态变量包括:用static定义的变量,以及在函数以外定义的变量。静态变量的默认值为0。

作用域就是名称在多大的范围之内可见。

一般变量只在其所在的代码块中可见。但如果它所在的代码块中的代码块定义了一个跟它同名的变量,则它就会被屏蔽掉。

链接性分为外部链接和内部链接

其中,声明在函数之外的自动变量有外部链接
外部链接的变量可以在别的文件中用关键字extern声明,然后对其访问。
在函数内部定义的变量都没有链接性,在函数外面定义的自动变量有外部链接,在函数外面定义的静态变量有内部链接。

用new来分配的空间存在堆中,只有delete了它才会被释放掉

9.3名称空间

当你想定义两个名字一样的函数、结构体或者函数时,可以将他们放在不同的名称空间中以区别开。

#include <cstdio>

//declare namespace la which including int a
namespace la
{
    int a;
}
//declare namespace re which including int a too
namespace re
{
    int a;
}
int main()
{
    using namespace la;     //using complie
    la::a = 4;              
    printf("%d\n", la::a);
    re::a = 5;
    printf("%d\n", re::a);  
    printf("%d\n", a);      //because having using colpiled la, 'a' mean la::a; 
}

10 对象和类

这部分应该会很少文字,感觉代码更好理解。

10.1过程性编程和面向对象编程

类和结构的区别:结构默认的访问类型是public,而类的默认访问类型是private

10.3类的构造函数和析构函数

构造函数的名字与类名相同,没有返回类型。可以有多个构造函数,根据参数的不同来区别。

  • 没有参数的构造函数称为默认构造函数,用来初始化对象。
  • 下面的代码中分别定义了默认构造函数,

10.4 this指针

this指针指向当前对象的地址。
比如你定义了一个class

class Player
{
private:
    std::string team;
    std::string name;
    double salary;
    double height;
    double weight;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值