《C++标准程序库》- 学习笔记2–第四章

  • 1.(P33)

Pairs(对组)的定义
class pair可以将两个值视为一个单元。map和multimap就是通过pair来管理键值/实值(key/value)的。
在pair的定义中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
namespace std {
    template <class T1, class T2>
    struct pair {
        // member
        T1 first;
        T2 second;
        ...
        // copy construct with implicit conversions
        template <class U, class V>
        pair(cosnt pair<U, V> & p)
        : first(p.first), second(p.second) {
        }
    };
    ...
}

可以看到在copy构造函数时,使用了template,这是对于需要隐式转换的。如果是相同类型,则不是调用此构造函数,而是调用系统合成的copy构造函数。
对于上面代码实现的方法,在学习笔记1(http://www.wutianqi.com/?p=2025)中第二点讲到过。

  • 2.(P36)

生成Pair的便捷函数make_pair()

1
2
3
4
5
6
7
namespace std {
    // create value pair only by providing the values
    template <class T1, class T2>
    pair<T1, T2> make_pair(const T1 &x, const T2 &y) {
        return pair<T1, T2>(x, y);
    }
}

这样,可以通过:

1
std::make_pair(100, "TankyWoo");

来代替:

1
std::pair<int, string>(100, "TankyWoo");

不过,一个算式如果明确指出类型,则带有一个优势:产生出来的pair将有绝对明确的型别,比如:

1
std::pair<int, float>(100, 8.88);

1
std::make_pair(100, 8.88)

就不是一个类型,因为第二个元素中,前者是float类型,而后者是double类型(浮点型默认)。

  • 3.(P38)

Class auto_ptr
auto_ptr是这样一种指针:它是”它所指的对象”的拥有者(owner)。所以,当身为拥有着的auto_ptr被摧毁时,该对象也遭到摧毁。auto_ptr要求一个对象只能有一个拥有者,严禁一物二主。
比如:

1
2
3
4
5
6
void f()
{
    ClassA* ptr = new ClassA;
    ...
    delete ptr;
}

如果在…的代码中出现异常或return语句等,则ptr无法释放,而造成内存遗失。

1
2
3
4
5
void f()
{
    std::auto_ptr&lt;ClassA&gt; ptr(new ClassA);
    ...
}

这样就可以解决问题了。
注意,auto_ptr<>不允许使用一般指针惯用的赋值(assign)初始化方式,必须使用直接初始化
eg.

1
2
std::auto_ptr<ClassA> ptr1(new ClassA);   // Ok
std::auto_ptr<ClassA> ptr = new ClasssA; // Error
  • 4.(P40)

auto_ptr拥有权的转移
通过auto_ptr的copy构造函数和assignment操作符将对象拥有权交出去。
eg.

1
2
// transfer ownership from ptr1 to ptr2
std::auto_ptr<ClassA> ptr2(ptr1)

1
2
std::auto_ptr<ClassA> ptr2;
ptr2 = ptr1;

如果ptr2被赋值前拥有一个对象,则赋值操作时会调用delete将该对象删除。
因为auto_ptr赋值时会交出拥有权,所以不要在函数的参数列表中使用auto_ptr,也不要以它做返回值。
可以通过引用(reference)传递auto_ptr.
常数型auto_ptr可以减小”不经意转移拥有权”。它意味着不能更改auto_ptr的拥有权,但可以更改auto_ptr所拥有的对象。
eg.

1
2
3
4
5
const std::auto_ptr<int> p(new int);
std::auto_ptr<int> q(new int);
*p = 42;  // OK
*p = *q;  // OK
p = q;     // Error

最后来一个实例:

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
30
31
32
33
34
35
36
#include <iostream>
using namespace std; 
 
template <class T>
ostream& operator<< (ostream& strm, const auto_ptr<T>& p)
{
    if (p.get() == NULL) {
         strm << "NULL";
    }
    else {
        strm << *p;
    }
    return strm;
} 
 
int main()
{
 
    auto_ptr<int> p(new int(42));
    auto_ptr<int> q;
    cout << "after initialization:" << endl;
    cout << " p: " << p << endl;
    cout << " q: " << q << endl;
    q = p;
    cout << "after assigning auto pointers:" << endl;
    cout << " p: " << p << endl;
    cout << " q: " << q << endl; 
    *q += 13;
    p = q;
    cout << "after changed and assignment:" << endl;
    cout << " p: " << p << endl;
    cout << " q: " << q << endl; 
 
    system("PAUSE");
    return EXIT_SUCCESS;
}

输出:

after initialization:
p: 42
q: NULL
after assigning auto pointers:
p: NULL
q: 42
after changed and assignment:
p: 55
q: NULL

  • 5.(P66)

三个辅助函数: min(), max(), swap()
都定义在头文件

  • 6.(P71)

头文件定义了一些常用的常数、宏、型别和函数。
中的定义项
NULL  指针值,表示”未定义”或”无值”
size_t  一种无正负号的型别,用来表示大小(例如元素个数)
ptrdiff_t  一种带有正负号的型别,用来表示指针之间的距离
offsetof  表示一个成员在struct或union的偏移量

中定义项
exit(int status)  退出(离开,exit)程序
EXIT_SUCCESS 程序正常结束
EXIT_FAILURE  程序不正常结束
abort()  退出程序(在某些系统上可能导致崩溃)
atexit(void(*function)()) 退出(exit)程序时调用某些函数
下面对offsetof介绍下:

offsetof :
Retrieves the offset of a member from the beginning of its parent structure.

size_t offsetof(structName, memberName);

Parameters:
structName : Name of the parent data structure.
memberName :Name of the member in the parent data structure for which to determine the offset.

Return Value : offsetof returns the offset in bytes of the specified member from
the beginning of its parent data structure. It is undefined for bit fields.
Remarks :
The offsetof macro returns the offset in bytes of memberName from the beginning of the structure specified by structName. You can specify types with the struct keyword.

Note :
offsetof is not a function and cannot be described using a C prototype.

我举了一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Author: Tanky Woo
// Blog:    www.WuTianQi.com
#include <cstddef>
#include <iostream>
using namespace std; 
 
typedef struct TK {
    char a;
    int b;
    char c;
}TK; 
 
int main()
{
    cout << offsetof(TK, a) << endl;
    cout << offsetof(TK, b) << endl;
    cout << offsetof(TK, c) << endl;
    system("PAUSE");
    return EXIT_SUCCESS;
}

里面涉及到了内存对齐问题,关于内存对齐的详细文章,我在其他地方发过:

http://www.cppleyuan.com/viewthread.php?tid=17&highlight=%E5%86%85%E5%AD%98%E5%AF%B9%E9%BD%90

http://www.cppleyuan.com/viewthread.php?tid=18&highlight=%E5%86%85%E5%AD%98%E5%AF%B9%E9%BD%90

发布者

Tanky Woo

Tanky Woo,[个人主页:https://tankywoo.com] / [新博客:https://blog.tankywoo.com]

《《C++标准程序库》- 学习笔记2–第四章》有59个想法

发表评论

电子邮件地址不会被公开。 必填项已用*标注