亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫(kù)
最近訪問板塊 發(fā)新帖
查看: 5681 | 回復(fù): 4
打印 上一主題 下一主題

關(guān)于寫時(shí)復(fù)制(COW) [復(fù)制鏈接]

論壇徽章:
1
榮譽(yù)會(huì)員
日期:2011-11-23 16:44:17
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2006-09-26 15:39 |只看該作者 |倒序?yàn)g覽
大部份的STL在實(shí)現(xiàn)string時(shí),都采用COW來保證其高效性。即多個(gè)類會(huì)共用一個(gè)數(shù)據(jù)緩沖區(qū)(buffer),在拷貝構(gòu)造、賦值等操作時(shí),并不會(huì)對(duì)buffer進(jìn)行復(fù)制。僅在需要對(duì)buffer進(jìn)行修改,而且此buffer已與別的類共享了,才會(huì)開辟空間,將buffer復(fù)制一份進(jìn)行修改。同樣在析構(gòu)時(shí),如果buffer與與別的類共享,也不會(huì)釋放空間。
舉個(gè)例子:
  1. #include <stdio.h>
  2. #include <string>
  3. using namespace std;

  4. int main()
  5. {
  6.     string test1 = "hello";
  7.     string test2(test1);

  8.     printf("test1:%p test2:%p\n", test1.c_str(), test2.c_str());
  9. }
復(fù)制代碼

運(yùn)行結(jié)果:
test1:0x90a9014 test2:0x90a9014

可見兩個(gè)地址是相等的,它們共用了同一個(gè)緩沖區(qū)。
什么時(shí)候會(huì)引起數(shù)據(jù)區(qū)的復(fù)制?當(dāng)然是要修改string的值的時(shí)候
  1. #include <stdio.h>
  2. #include <string>
  3. using namespace std;

  4. int main()
  5. {
  6.     string test1 = "hello";
  7.     string test2(test1);

  8.     printf("test1:%p test2:%p\n", test1.c_str(), test2.c_str());
  9.     test2[0] = 'w';
  10.     printf("test1:%p test2:%p\n", test1.c_str(), test2.c_str());
  11. }
復(fù)制代碼

運(yùn)行結(jié)果:
test1:0x9e85014 test2:0x9e85014
test1:0x9e85014 test2:0x9e8502c

可以看到test2發(fā)生了變化。
再進(jìn)一步,編譯如何確定程序要對(duì)buffer進(jìn)行修改,從而去開辟新的空間呢?
程序一般是通過[]運(yùn)算符、iterator去訪問并修改數(shù)據(jù)。很自然地認(rèn)為,對(duì)于左值會(huì)引起數(shù)據(jù)復(fù)制,而右值不會(huì)。但實(shí)際上,編譯沒這么做?赡苁亲笾祷蛴抑档呐卸ú]有那么簡(jiǎn)單吧?
  1. #include <stdio.h>
  2. #include <string>
  3. using namespace std;

  4. int main()
  5. {
  6.     string test1 = "hello";
  7.     string test2(test1);

  8.     printf("test1:%p   test2:%p\n", test1.c_str(), test2.c_str());
  9.      printf("test1:%p   test2:%p\n", &test1[0], &test2[0]);
  10. }
復(fù)制代碼

運(yùn)行結(jié)果:
test1:0x8a4a014   test2:0x8a4a014
test1:0x8a4a014   test2:0x8a4a02c

test2發(fā)生了變化。
看一下源碼:
  1.       const_reference
  2.       operator[] (size_type __pos) const
  3.       {
  4.         _GLIBCXX_DEBUG_ASSERT(__pos <= size());
  5.         return _M_data()[__pos];
  6.       }

  7.       reference
  8.       operator[](size_type __pos)
  9.       {
  10.         _GLIBCXX_DEBUG_ASSERT(__pos < size());
  11.         _M_leak();
  12.         return _M_data()[__pos];
  13.       }
復(fù)制代碼

也就是說判定是否可能有寫操作是與類的類型相關(guān)的,如果是const string,則不復(fù)制,如果是string,則一定復(fù)制
再看看這個(gè):
  1. #include <stdio.h>
  2. #include <string>
  3. using namespace std;

  4. int main()
  5. {
  6.     string test1 = "hello";
  7.     string test2(test1);

  8.     printf("test1:%p test2:%p\n", test1.c_str(), test2.c_str());
  9.     const string &test3 = test1;
  10.     const string &test4 = test2;
  11.     printf("test1:%p test2:%p\n", &test3[0], &test4[0]);
  12. }
復(fù)制代碼

結(jié)果就是:
test1:0x8c62014  test2:0x8c62014
test1:0x8c62014  test2:0x8c62014

當(dāng)然這樣寫很難受,憑什么要搞兩個(gè)const的引用出來。
這樣就比較自然:
  1. #include <stdio.h>
  2. #include <string>
  3. using namespace std;

  4. void proc(const string& test1, const string& test2)
  5. {
  6.     printf("test1:%p test2:%p\n", &test1[0], &test2[0]);
  7. }

  8. int main()
  9. {
  10.     string test1 = "hello";
  11.     string test2(test1);

  12.     printf("test1:%p test2:%p\n", test1.c_str(), test2.c_str());
  13.     proc(test1, test2);
  14. }
復(fù)制代碼

也是說一定要嚴(yán)格地確定數(shù)據(jù)類型是否是const的,如果函數(shù)里不修改修,則傳const,良好的習(xí)慣有利于代碼質(zhì)量的提高。
string和char *是無法共享數(shù)據(jù)區(qū)的,所以用c++就盡量少用指針,兩種風(fēng)格合在一起,效率是最低的。

[ 本帖最后由 yuxh 于 2006-9-26 15:45 編輯 ]

論壇徽章:
1
榮譽(yù)會(huì)員
日期:2011-11-23 16:44:17
2 [報(bào)告]
發(fā)表于 2006-09-26 15:42 |只看該作者
年紀(jì)越來越老,是不是越來越啰嗦了呢?
但一般對(duì)于vector或者list是沒有COW的,要拷貝就全拷。
但可以自己封裝,隨便寫了一個(gè),還不是很完善:
  1. #ifndef _COW_CONTAINER_
  2. #define _COW_CONTAINER_ 1

  3. #include <vector>
  4. #include <list>
  5. using namespace std;

  6. template<typename _Tp>
  7. class cow_container
  8. {
  9. public:
  10.   typedef typename _Tp::value_type value_type;
  11.   typedef typename _Tp::reference reference;
  12.   typedef typename _Tp::const_reference const_reference;
  13.   typedef typename _Tp::iterator iterator;
  14.   typedef typename _Tp::const_iterator const_iterator;
  15.   cow_container()
  16.   {
  17.     m_pCowNode = new cow_node;
  18.     m_pCowNode->m_refCount = 0;
  19.   }
  20.   cow_container(const cow_container& __cc)
  21.   {
  22.     m_pCowNode = __cc.m_pCowNode;
  23.     m_pCowNode->m_refCount++;
  24.   }
  25.   cow_container(const_iterator _begin, const_iterator _end)
  26.   {
  27.     m_pCowNode = new cow_node;
  28.     m_pCowNode->m_refCount = 0;
  29.     const_iterator itr;
  30.     for(itr = _begin(); itr != _end; ++itr) {
  31.       m_pCowNode->m_data.push_back(*itr);
  32.     }
  33.   }
  34.   cow_container(const_iterator _begin, size_t _n)
  35.   {
  36.     m_pCowNode = new cow_node;
  37.     m_pCowNode->m_refCount = 0;
  38.     const_iterator itr;
  39.     for(itr = _begin(); itr < _begin + _n; ++itr) {
  40.       m_pCowNode->m_data.push_back(*itr);
  41.     }
  42.   }
  43.   cow_container(const _Tp& __cc)
  44.   {
  45.     m_pCowNode = new cow_node;
  46.     m_pCowNode->m_refCount = 0;
  47.     m_pCowNode->m_data = __cc;
  48.   }
  49.   ~cow_container()
  50.   {
  51.     if(m_pCowNode->m_refCount == 0)
  52.       delete m_pCowNode;
  53.     else
  54.       m_pCowNode->m_refCount--;
  55.   }
  56.   cow_container &operator=(const cow_container& __cc)
  57.   {
  58.     if(m_pCowNode != __cc.m_pCowNode) {
  59.       if(m_pCowNode->m_refCount == 0)
  60.         delete m_pCowNode;
  61.       else
  62.         m_pCowNode->m_refCount--;
  63.       m_pCowNode = __cc.m_pCowNode;
  64.       m_pCowNode->m_refCount++;
  65.     }
  66.     return *this;
  67.   }
  68.   cow_container &operator=(const _Tp& __cc)
  69.   {
  70.     if(m_pCowNode != __cc.m_pCowNode) {
  71.       if(m_pCowNode->m_refCount == 0)
  72.         delete m_pCowNode;
  73.       else
  74.         m_pCowNode->m_refCount--;
  75.       m_pCowNode = new cow_node;
  76.       m_pCowNode->m_refCount = 0;
  77.       m_pCowNode->m_data = __cc;
  78.     }
  79.     return *this;
  80.   }
  81.   const_iterator begin() const
  82.   {
  83.     return m_pCowNode->m_data.begin();
  84.   }
  85.   const_iterator end() const
  86.   {
  87.     return m_pCowNode->m_data.end();
  88.   }
  89.   iterator begin()
  90.   {
  91.     do_copy();
  92.     return m_pCowNode->m_data.begin();
  93.   }
  94.   iterator end()
  95.   {
  96.     do_copy();
  97.     return m_pCowNode->m_data.end();
  98.   }
  99.   const_reference operator[](int _n) const
  100.   {
  101.     return m_pCowNode->m_data[_n];
  102.   }
  103.   reference operator[](int _n)
  104.   {
  105.     do_copy();
  106.     return m_pCowNode->m_data[_n];
  107.   }
  108.   void push_back(const value_type& _val)
  109.   {
  110.     do_copy();
  111.     m_pCowNode->m_data.push_back(_val);
  112.   }
  113.   iterator insert(iterator __position, const value_type& __x)
  114.   {
  115.     do_copy();
  116.     m_pCowNode->m_data.insert(__position, __x);
  117.   }

  118.   const _Tp& container() const
  119.   {
  120.     return m_pCowNode->m_data;
  121.   }
  122. private:
  123.   struct cow_node
  124.   {
  125.     int          m_refCount;
  126.     _Tp          m_data;
  127.   };
  128.   cow_node     *m_pCowNode;

  129.   void do_copy()
  130.   {
  131.     if(m_pCowNode->m_refCount > 0) {
  132.       const _Tp &bak = m_pCowNode->m_data;
  133.       m_pCowNode->m_refCount--;
  134.       m_pCowNode = new cow_node;
  135.       m_pCowNode->m_refCount = 0;
  136.       m_pCowNode->m_data = bak;
  137.     }
  138.   }
  139. };

  140. template<class _Tp>
  141. class VECTOR:public cow_container< vector<_Tp> > { };

  142. template<class _Tp>
  143. class LIST:public cow_container< list<_Tp> > { };

  144. #endif
復(fù)制代碼

[ 本帖最后由 yuxh 于 2006-9-26 15:48 編輯 ]

論壇徽章:
0
3 [報(bào)告]
發(fā)表于 2006-09-26 20:30 |只看該作者
我的直覺string是靠RefCount來判斷是否COW, 看來得在查查.
reve 該用戶已被刪除
4 [報(bào)告]
發(fā)表于 2006-09-26 23:12 |只看該作者
提示: 作者被禁止或刪除 內(nèi)容自動(dòng)屏蔽

論壇徽章:
39
2017金雞報(bào)曉
日期:2017-02-08 10:39:4219周年集字徽章-周
日期:2023-04-15 12:02:2715-16賽季CBA聯(lián)賽之深圳
日期:2023-02-16 14:39:0220周年集字徽章-年
日期:2022-08-31 14:25:28黑曼巴
日期:2022-08-17 18:57:0919周年集字徽章-年
日期:2022-04-25 13:02:5920周年集字徽章-20	
日期:2022-03-29 11:10:4620周年集字徽章-年
日期:2022-03-14 22:35:1820周年集字徽章-周	
日期:2022-03-09 12:51:3220周年集字徽章-年
日期:2022-02-10 13:13:4420周年集字徽章-周	
日期:2022-02-03 12:09:4420周年集字徽章-20	
日期:2022-01-25 20:14:27
5 [報(bào)告]
發(fā)表于 2006-09-26 23:21 |只看該作者
樓主總能給我們帶來驚喜,感謝。
您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號(hào)-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號(hào):11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國(guó)互聯(lián)網(wǎng)協(xié)會(huì)會(huì)員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請(qǐng)注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP