Blog·Tanky WooABOUTRSS

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

24 Jan 2011
这篇博客是从旧博客 WordPress 迁移过来,内容可能存在转换异常。

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

namespace std {
    template 
    struct pair {
        // member
        T1 first;
        T2 second;
        ...
        // copy construct with implicit conversions
        template 
        pair(cosnt pair & p)
        : first(p.first), second(p.second) {
        }
    };
    ...
}

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

生成Pair的便捷函数make_pair()

namespace std {
    // create value pair only by providing the values
    template 
    pair make_pair(const T1 &x;, const T2 &y;) {
        return pair(x, y);
    }
}

这样,可以通过:

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

来代替:

std::pair(100, "TankyWoo");

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

std::pair(100, 8.88);

std::make_pair(100, 8.88)

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

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

void f()
{
    ClassA* ptr = new ClassA;
    ...
    delete ptr;
}

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

void f()
{
    std::auto_ptr<ClassA> ptr(new ClassA);
    ...
}

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

std::auto_ptr ptr1(new ClassA);   // Ok
std::auto_ptr ptr = new ClasssA; // Error

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

// transfer ownership from ptr1 to ptr2
std::auto_ptr ptr2(ptr1) 

std::auto_ptr ptr2;
ptr2 = ptr1;

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

const std::auto_ptr p(new int);
std::auto_ptr q(new int);
*p = 42;  // OK
*p = *q;  // OK
p = q;     // Error

最后来一个实例:

#include 
using namespace std; 

template 
ostream& operator<< (ostream& strm, const auto_ptr& p)
{
    if (p.get() == NULL) {
         strm << "NULL";
    }
    else {
        strm << *p;
    }
    return strm;
} 

int main()
{

    auto_ptr p(new int(42));
    auto_ptr 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

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

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

中定义项 exit(int status)  退出(离开,exit)程序 EXITSUCCESS 程序正常结束 EXITFAILURE  程序不正常结束 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.

我举了一个例子:

// Author: Tanky Woo
// Blog:    www.WuTianQi.com
#include 
#include 
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