iT邦幫忙

0

C++ Primer 5th Edition Exercises(練習題)13.32

Would the pointerlike version of HasPtr benefit from defining a swap function? If so, what is the benefit? If not, why not?

類指標行為的HasPtr是否也會從定義了swap函式而得到方便?若是,有什麼便利之處;若否,又是為什麼?

恐怕就是拷貝指定運算子定義時,對參考計數操作上,若仍須在撰寫程式碼時還要加上如同前面那樣自行寫定參考計數的計算,那就沒有方便太多了。
測試結果卻是OK的,和類值的是一樣便利!參考計數在swap及copy and swap後並無影響:

HasPtr.h

#ifndef HASPTR_H
#define HASPTR_H
#include<string>
//#include<iostream> //因為.cpp檔已include了,所以此可省略引用iostream
class HasPtr//類指標行為的類別
{
    friend void swap(HasPtr&,HasPtr&);
public:
    //預設建構器
    HasPtr(const std::string& s = std::string()) : ps(new std::string(s)), i(0), user_cnt(new size_t(1)) {  }
    //拷貝建構器
    HasPtr(const HasPtr& hp) :ps(hp.ps), i(0), user_cnt(hp.user_cnt) { 
        ++* user_cnt; 
        std::cout << "拷貝建構器 阿彌陀佛" <<std::endl;
    }
    //拷貝指定運算子
    //HasPtr& operator=(const HasPtr& hp) {
    //  ++* hp.user_cnt;
    //  //和解構器~HasPtr()做的是同一件事:
    //  //if (-- * user_cnt == 0)
    //  //{
    //  //  delete ps;
    //  //  delete user_cnt;
    //  //}//以上和解構器~HasPtr()做的是同一件事,只是解構器似乎不能被呼叫,故可另寫一個介面或成員函式來用
    //  destroy();
    //  if (*user_cnt != 0&&ps!=hp.ps) {//不是自拷貝/指定時才執行
    //      ps = hp.ps;
    //      i = hp.i;
    //      user_cnt = hp.user_cnt;
    //  }
    //  return *this;
    //}
    HasPtr& operator=(HasPtr);
    
    ~HasPtr() {
        //if (-- * user_cnt == 0) {
        //  delete ps;
        //  delete user_cnt;
        //}
        destroy();
        std::cout << "解構器 阿彌陀佛" << std::endl;
    }
private:
    std::string* ps;
    int i;
    size_t* user_cnt;
    void destroy() {
        if (-- * user_cnt == 0) {
            delete ps;
            delete user_cnt;
        }
    }
};

void swap(HasPtr& lhs,HasPtr& rhs) {
    using std::swap;
    swap(lhs.ps, rhs.ps);
    swap(lhs.i, rhs.i);
    swap(lhs.user_cnt, rhs.user_cnt);

}

//copy and swap(拷貝對調)
HasPtr& HasPtr::operator=(HasPtr hp) {
    swap(*this, hp);
    //因為引數hp在傳值時已經將參考計數器遞增了,故不用以下此行添足
    //++* this->user_cnt;//參考計數只要顧到右運算元要遞增就好,左運算元遞增則交給被置換後的hp區域變數摧毀時呼叫的解構器來判斷
    return *this;   
}
#endif // !HASPTR_H

.cpp

#include<iostream>//因為這裡include,所以HasPtr.h才可以不用再次include它;如果這行省略,HasPtr.h編譯上就會出現錯誤
#include"HasPtr.h"
using namespace std;

int main() {
    HasPtr hp("孫守真"), hp1("南無阿彌陀佛"), hp2("淨空老法師"), hp3("海賢老和尚"),hp4("常律老和尚"),hp5("白雲老禪師"),hp6;
    hp6 = hp;
    hp = hp1;
}

https://github.com/oscarsun72/prog1-C-Primer-5th-Edition-s-Exercises/tree/exercise13_32_HasPtr_pointerlike_swap/prog1
臉書直播


尚未有邦友留言

立即登入留言