Effective C++ 学习笔记
2011-07-27 21:20 Clingingboy 阅读(660) 评论(0) 收藏 举报
基于此文档
http://wenku.baidu.com/view/ef989106e87101f69e3195db.html
条款13:以对象管理资源
目标:为确保资源被释放
1.获得资源后立即放进管理对象
2.管理对象运用析构函数确保资源被释放
做法:
之前
void f()
{
    Investment *pInv = createInvestment();         // call factory function
    ...                                            // use pInv
    delete pInv;                                   // release object
}
之后
void f()
{
    std::auto_ptr<Investment> pInv(createInvestment());  
}
关于std::auto_ptr和std::tr1::shared_ptr用法不再叙述
条款14:在资源管理类中小心coping行为
class Lock {
public:
    explicit Lock(Mutex *pm)
        : mutexPtr(pm)
    { lock(mutexPtr); }                          // acquire resource
    ~Lock() { unlock(mutexPtr); }                // release resource
private:
    Mutex *mutexPtr;
};
coping行为
Lock ml1(&m);                      // lock m
Lock ml2(ml1); 
问题:“当一个RAII对象被复制,会发生什么事?”
选择做法:
1.禁止复制
class Lock: private Uncopyable {            // prohibit copying — see
public:                                     // Item 6
    ...                                        // as before
};
2.(最为普遍方法)利用std::tr1::shared_ptr的删除器做引用计数(当计数为0时调用的函数,但不删除指针)
class Lock {
public:
    explicit Lock(Mutex *pm)       // init shared_ptr with the Mutex
        : mutexPtr(pm, unlock)         // to point to and the unlock func
    {                              // as the deleter
        lock(mutexPtr.get());   // see Item 15 for info on "get"
    }
private:
    std::tr1::shared_ptr<Mutex> mutexPtr;    // use shared_ptr
};   
3.深拷贝资源,但不用时要做删除动作
4.利用auto_ptr做资源拥有权的转移
条款15:在资源管理类中提供对原始资源的访问
如下代码
std::tr1::shared_ptr<Investment> pInv(createInvestment());  // from Item 13
int daysHeld(const Investment *pi);        // return number of days
int days = daysHeld(pInv);                // error!
int days = daysHeld(pInv.get());      
两种方式:
1.显示转换:get方法就是显示转换
class Font {                           // RAII class
public:
    ...                       // C API does
    FontHandle get() const { return f; }
private:
    FontHandle f;                        // the raw font resource
    ...
};
changeFontSize(f.get(), newFontSize); // explicitly convert 
2.隐式转换
class Font {
public:
    ...
        operator FontHandle() const { return f; }        // implicit conversion function
    ...
};
changeFontSize(f, newFontSize);     // implicitly convert
显然各有优缺点,但显示转换不易被误用,如std: string的显示转换方法
条款17:以独立语句将newd对象置入智能指针
int priority();
void processWidget(std::tr1::shared_ptr<Widget> pw, int priority);
如何传参的问题:
重点:保证传入的指针在异常的时候可以释放资源
processWidget(std::tr1::shared_ptr<Widget>(new Widget), priority());
以上做法可能有错误,如果执行顺序如下,而priority函数发生了错误,那么内存无法释放
- 
    
Execute "new Widget".
 - 
    
Call priority.
 - 
    
Call the tr1::shared_ptr constructor.
 
保险的做法,在外部声明
std::tr1::shared_ptr<Widget> pw(new Widget);  // store newed object
processWidget(pw, priority());                // this call won't leak
第四章:设计与声明
这一章大多与设计有关
条款18:让接口容易被正确使用,不易被误用
让接口更易被理解和使用
之前:
class Date {
public:
    Date(int month, int day, int year);
    ...
};
以类代替(请勿模仿,任何事物防不胜防,看需求而定)
struct Day {            struct Month {                struct Year {
    explicit Day(int d)     explicit Month(int m)         explicit Year(int y)
        :val(d) {}              :val(m) {}                    :val(y){}
    int val;                int val;                      int val;
};                      };                            };
class Date {
public:
    Date(const Month& m, const Day& d, const Year& y);
    ...
};
Date d(30, 3, 1995);                      // error! wrong types
Date d(Day(30), Month(3), Year(1995));    // error! wrong types
Date d(Month(3), Day(30), Year(1995));    // okay, types are correct
条款 21:必须返回对象时,别妄想返回其reference
拒绝一下两种写法,c#和java的开发者一定很不习惯
const Rational& operator*(const Rational& lhs,   // warning! bad code!
    const Rational& rhs)
{
    Rational result(lhs.n * rhs.n, lhs.d * rhs.d);
    return result;
}
const Rational& operator*(const Rational& lhs,   // warning! more bad
    const Rational& rhs)   // code!
{
    Rational *result = new Rational(lhs.n * rhs.n, lhs.d * rhs.d);
    return *result;
}
必须要返回对象是,请返回一个新对象
inline const Rational operator*(const Rational& lhs, const Rational& rhs)
{
    return Rational(lhs.n * rhs.n, lhs.d * rhs.d);
}
条款 22:将成员变量声明为private
真的没什么好讲的,学过c#和java的人都知道
class AccessLevels {
public:
    ...
    int getReadOnly() const        { return readOnly; }
    void setReadWrite(int value)   { readWrite = value; }
    int getReadWrite() const       { return readWrite; }
    void setWriteOnly(int value)   { writeOnly = value; }
private:
    int noAccess;                         // no access to this int
    int readOnly;                         // read-only access to this int
    int readWrite;                        // read-write access to this int
    int writeOnly;                        // write-only access to this int
};
条款 23:宁以non-member、non-friend替换member函数
class WebBrowser {
public:
    ...
    void clearCache();
    void clearHistory();
    void removeCookies();
    //void clearBrowser(WebBrowser& wb)
    //{
    //    wb.clearCache();
    //    wb.clearHistory();
    //    wb.removeCookies();
    //}
    ...
};
void clearBrowser(WebBrowser& wb)
{
    wb.clearCache();
    wb.clearHistory();
    wb.removeCookies();
}
将便利函数放在外部,不要为类添加太多的类成员(意思就是只添加必要的),基本属于设计问题
条款 24:若所有参数皆需类型转换,请为此采用non-member函数
如下示例代码
class Rational {
public:
    Rational(int numerator = 0,        // ctor is deliberately not explicit;
        int denominator = 1);     // allows implicit int-to-Rational
    // conversions
    int numerator() const;             // accessors for numerator and
    int denominator() const;           // denominator — see Item 22
    const Rational operator*(const Rational& rhs) const;
private:
    ...
};
其提供了隐式转换功能:
Rational oneEighth(1, 8);
Rational oneHalf(1, 2);
Rational result = oneHalf * oneEighth;            // fine
result = result * oneEighth;                      // fine
更加贪婪的做法
result = oneHalf * 2;                       // fine
result = 2 * oneHalf;                       // error!
为了支持2的隐式转换,做法是实现一个non-member的操作符重载
const Rational operator*(const Rational& lhs,     // now a non-member
    const Rational& rhs)     // function
{
    return Rational(lhs.numerator() * rhs.numerator(),
        lhs.denominator() * rhs.denominator());
}
Rational oneFourth(1, 4);
Rational result;
result = oneFourth * 2;                           // fine
result = 2 * oneFourth;                           // hooray, it works!
记得是所有参数
                    
                
                
            
        
浙公网安备 33010602011771号