模板的具体化和实例化

什么是模板的具体化和实例化呢?有以下模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
template <typename T>
void Swap(T &a, T &b);

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

int main()
{
using namespace std;
int i = 10;
int j = 20;
Swap(i, j); // 标志1
...
...
}

在上面的模板函数声明中,声明一个交换类型为T的两个元素。代码包含函数模板并不会生产函数定义,它只是一个用于生产函数定义的方案。当编译器使用模板为特定类型生产函数定义时(程序标志1处),得到的是模板实例化,值得注意的是这里实例化的方式为隐式实例化,因为编译器发现你用的int类型参数,所以就隐式实例化。
在C++中,还有一种实例化方式:显式实例化,语法如下:

1
template void Swap<int>(int, int);  //显式实例化

与实例化不太一样的是显式具体化,具体的声明语法如下:

1
2
template <> void Swap(int &, int &);
template <> void Swap<int>(int &, int &);

显示具体化不同的是:需要专门为int类型显式地定义函数定义,显式具体化声明在关键字template后包含<>,而显式实例化没有。

此时,我们会发现有很多不同的函数定义,那么我们使用某个函数的时候,编译器到底使用的哪个函数原型呢? 编译器选择原型的时候,非模板函数版本 > 显式具体化 > 通用模板版本。

另外一点,同一个类型的显示实例化和显式具体化不能同时使用,会出错。

C++中如何输出char型指针地址

  • C++ 中std::cout对于char类型的指针,将默认输出这个类型指向的字符串,也就是:
    1
    2
    3
    4
    char * temp = "Hello, CPP.\n";
    std::cout << temp << endl;

    OUTPUT: Hello, CPP

那么我们要想输出这个字符串的地址怎么办???

  • 首先,我们要清楚为什么会这样呢,因为如果是int类型的指针就不会呀。这是因为C++标准库中IO类对’<<’运算符进行了重载,因此呢, 在遇到 char * 类型数据的时候,就自动使用相应的重载函数,把那个char型指针指向的字符串输出了。
  • 那么,How 2 solve this problem? 类型转换呀,你把它转换为int型指针? 这是可以的, 但是这时下策。使用’static_cast‘,把char型指针转换为无类型指针。如下:

    1
    2
    3
    4
    5
    6
    char * temp = "Hello, CPP.\n";
    std::cout << temp << endl;
    std::cout << static_cast<const void *>(temp) << endl;
    OUTPUT:
    Hello, CPP
    某个地址
  • 一些学渣还会有疑问,static_cast<>()这是什么鬼?那么拾起那么《C++ primer》,你会发现C++还是很有趣的。

派生类与基类之间的特殊关系

  • 继承是C++中一项非常重要的特性,继承派生使得C++的代码重用实现可能。基类与其派生类之间也有着较为特殊的关系
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class person{
    private:
    string name;
    double height;
    public:
    void Funciton_One();
    };
    class student : public person{
    private:
    int student_ID;
    public:
    void Funciton_TWo();
    }

由上述简要代码可以知道,student类从person类派生出来,继承了person类的实现(存储了基类数据成员)与接口(可以使用基类方法)。
重点
基类指针可以在不进行显式转换的情况下,指向派生类对象;同理,
基类引用也可以在不进行显式转换的情况下引用派生类对象。
但是,反过来确实不允许的,

1
2
3
4
5
6
person Zhang(……);
student Lee(……);
person * Temp1 = &Lee; // Allowed
person & Temp2 = Lee; // Allowed
student * temp1 = &Zhang; // Not Allowed
student & temp2 = Zhang; // Not Allowed

从上面代码可以看出这一特殊的关系。虽然基类引用和指针可以引用和指向派生类对象,但是基类引用和指针只能调用基类方法。这也正常,你试想,使用基类引用为派生类对象调用基类方法,显然是可以的,因为派生类继承了基类方法;相反,如果使用派生类引用为基类对象调用派生类方法,这明显会发生错误。
这一关系也存在于以基类引用(指针)作为形参的函数。

HigtGUI的初识

  1. imread()函数
    Mat imread(const string & filename, int flags = 1);
    其中第一个参数表示要读取的图像文件名, const string &类型的filename。值得注意的是图像的路径。支持多种类型的图像载入,主流的有bmp\jpg\jpeg\png\ppm\pgm\ras\tif等类型。
    第二个参数表示载入标识,就是需要以何种方式把原图像呈现,默认参数为1。可以在OpenCV的图像标识枚举中选取:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
enum
{
/* 8bit, color or not */
//新的版本中已经取消,忽略,原通道读取
CV_LOAD_IMAGE_UNCHANGED =-1,
/* 8bit, gray */
//原图像转换为灰度图像输出
CV_LOAD_IMAGE_GRAYSCALE =0,
/* ?, color */
//原图像转换为彩色图像输出,如果原图像是灰度图像,输出还是灰度
CV_LOAD_IMAGE_COLOR =1,
/* any depth, ? */
//如果图像深度为16或者32位,则输出相应深度的图像,否则转换为8位深度图像
CV_LOAD_IMAGE_ANYDEPTH =2,
/* ?, any color */
//原图像色彩保持不变
CV_LOAD_IMAGE_ANYCOLOR =4
};

但是OpenCV3中这些宏都失效,故采用数字。

1
Mat img = imread("pic.jpg",2|4)  //载入无损的源图像

Read More

c++成员运算符

总结一下成员运算符的简单知识。

  • 成员运算符有直接成员运算符 . 和间接成员运算符 ->

  • 直接成员运算符 ‘.’
    直接成员运算符主要是在直接引用,类本身以及内部引用时使用。人话就是对象使用

  • 间接成员运算符 ‘->’
    间接成员运算符主要是在间接引用时使用。人话就是指向对象的指针使用

  • 有时,C++新手在指定结构成员时,搞不清楚何时应使用句点运算符,何时应使用箭头运算符。规则很简单,如果结构标识符是结构名称,则使用句点运算符(直接成员运算符);如果标识符是指向结构的指针,则使用箭头运算符。

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//利用结构,演示直接成员运算符和间接成员运算符的用法

#include <iostream>

struct inflatable
{
char name[20];
float volume;
double price;
};

int main()
{
using namespace std;
inflatable *ps = new inflatable;
cout << "enter name of inflable item: ";
cin.get(ps->name,20);
cout << "enter volume in cubic feet : ";
cin >> (*ps).volume;
cout << "enter price : $";
cin >> ps->price;
cout << "Name: " << (*ps).name <<endl;
cout << "volume : "<< ps->volume <<"cubic feet\n";
cout << "Price: $" << ps->price <<endl;
system("pause");
delete ps;

return 0;
}

sizeof和strlen的区别

在一些场景下,希望得到数组的大小,字符串的长度,char型数组的长度等等,很自然想到sizeof以及strlen,但是非常容易搞混弄错.下面简要列出一些区别:

  1. sizeof操作符的结果类型是size_t,它在头文件中typedef为unsigned int类型。
    该类型保证能容纳实现所建立的最大对象的字节大小。

  2. sizeof是操作符,strlen是函数。

  3. sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以’’\0’’结尾的。
    sizeof还可以用函数做参数,比如:

    1
    2
    short f();
    printf("%d\n", sizeof(f()));

输出的结果是 sizeof(short) ,即2。

Read More

C++指针注意事项

  • 一定要在对指针使用解除运算符(*)之前,将指针初始化为一个确定的适当的地址,这是关于使用指针的金科玉律。

  • 使用delete的关键在于,将他用于new分配的内存。这并不意味这要使用用于new的指针,而是用于new分配的地址。
    Example:

    1
    2
    3
    int *ps = new int;    //allocate memory
    int *pq = ps; //set second pointer to same block
    delete pq; //delete with second pointer

以上方法为同一使用new分配的空间,创建了两个指针,通常不会这么做,这将增加删除同一内存块两次的可能性。遵守

  • 使用new和delete时,需要以下规则。
  1. 不要使用delete来释放不是new分配的内存;
  2. 不要使用delete释放同一个内存块两次;
  3. 如果使用new []为数组分配内存,则应使用delete []来释放
  4. 如果使用new []为一个实体分配内存,则应使用delete来释放
  5. 对空指针使用delete是安全的

414. the third maxium number

  • Given a non-empty array of integers, return the third maximum number in this array. If it does not exist, return the maximum number. The time complexity must be in O(n).
    Example 1:
    1
    2
    3
    4
    5
    Input: [3, 2, 1]

    Output: 1

    Explanation: The third maximum is 1.

Example 2:

1
2
3
4
5
Input: [1, 2]

Output: 2

Explanation: The third maximum does not exist, so the maximum (2) is returned instead.

Example 3:

1
2
3
4
5
6
Input: [2, 2, 3, 1]

Output: 1

Explanation: Note that the third maximum here means the third maximum distinct number.
Both numbers with value 2 are both considered as second maximum.

解析

  • 翻译:给一个非空整型数组,返回第三大的数字,如果不存在则返回最大的数字,要求时间复杂度为0(n)

    Read More

1.two sum

  • Given an array of integers, return indices of the two numbers such that they add up to a specific target.

  • You may assume that each input would have exactly one solution.

Example:

1
2
3
4
Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

解析

Read More

461.hamming distance

  • The Hamming distance between two integers is the number of positions at which the corresponding bits are different.

  • Given two integers x and y, calculate the Hamming distance.

Note:
0 ≤ x, y < 2^31.

Example

1
2
3
4
5
6
7
8
9
10
Input: x = 1, y = 4

Output: 2

Explanation:
1 (0 0 0 1)
4 (0 1 0 0)
↑ ↑

The above arrows point to positions where the corresponding bits are different.

解析

  • 翻译:Hanmming Distance 就是两个整数[0 2^31]二进制表示对应位上不同位数的个数。给定X,Y求取两者的hamming distance

    Read More