【Boost】noncopyable:不可拷贝
【CSDN】:boost::noncopyable解析
 【Effective C++】:條款06_若不想使用編譯器自動生成地函數,就該明確拒絕
1.example
boost::noncopyable
 為什么要boost::noncopyable
 在c++中定義一個類的時候,如果不明確定義拷貝構造函數和拷貝賦值操作符,編輯器會為我們自動生成。
 但是有時候我們不需要類的復制語義,希望禁止復制類的實例。這時一個很經典的C++慣用語法,只要私有化拷貝構造函數和拷貝賦值操作函數即可。
 boost中的noncopyable為實現不可拷貝類提供了簡單清晰的解決方案。
boost::noncopyable源碼
//  Boost noncopyable.hpp header file  --------------------------------------////  (C) Copyright Beman Dawes 1999-2003. Distributed under the Boost
//  Software License, Version 1.0. (See accompanying file
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)//  See http://www.boost.org/libs/utility for documentation.#ifndef BOOST_CORE_NONCOPYABLE_HPP
#define BOOST_CORE_NONCOPYABLE_HPP#include <boost/config.hpp>namespace boost {//  Private copy constructor and copy assignment ensure classes derived from
//  class noncopyable cannot be copied.//  Contributed by Dave Abrahamsnamespace noncopyable_  // protection from unintended ADL
{class noncopyable{protected:
#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && !defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS)BOOST_CONSTEXPR noncopyable() = default;~noncopyable() = default;
#elsenoncopyable() {}~noncopyable() {}
#endif
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)noncopyable( const noncopyable& ) = delete;noncopyable& operator=( const noncopyable& ) = delete;
#elseprivate:  // emphasize the following members are privatenoncopyable( const noncopyable& );noncopyable& operator=( const noncopyable& );
#endif};
}typedef noncopyable_::noncopyable noncopyable;} // namespace boost#endif  // BOOST_CORE_NONCOPYABLE_HPP
2. noncopyable應用場景
1、單例模式各應用場景【略】
 2、類內含指針,其指向動態創建的對象,如:
template<class T>
class HomeForSale
{
public:T* data;HomeForSale() { data = new T; }~HomeForSale() { delete data; }
}void copy()
{HomeForSale<Home> m1;HomeForSale<Home> m2;m1 = m2; 
}執行拷貝后,m1.data指向m2.data所指對象,使m1.data無法釋放以致內存泄露,再者還存在雙重釋放的問題
 此情況可直接禁止拷貝,也可重載copy構造或copy assignment操作符解決【每次拷貝,內存刪舊開新】
3. part two
class noncopyable的基本思想就是把構造函數和析構函數設置為protected權限,這樣子類可以調用,但是外面的類不能調用,當子類需要定義構造函數的時候可以編譯通過。將拷貝構造函數和賦值構造函數設置為private,這就意味著除非子類定義自己的拷貝構造函數和拷貝賦值操作函數,否則外面的調用者不能夠通過拷貝構造和賦值等手段產生一個新的子類對象。
驗證
 文件test.cpp
#include<iostream>
#include <boost/noncopyable.hpp>class A : boost::noncopyable {
public:A(int a) {std::cout << a << std::endl; }
};int main(){A a1(1); //OKA a2(2); //OK//A a3 = a1; //編譯不能通過//A a4(a1);  //編譯不能通過A& a4 = a2;  //OKreturn 0;
}
編譯出錯:
In file included from /usr/local/include/boost/noncopyable.hpp:15:0,from test.cpp:2:
/usr/local/include/boost/core/noncopyable.hpp: 在復制構造函數‘A::A(const A&)’:
/usr/local/include/boost/core/noncopyable.hpp:38:7: 錯誤:‘boost::noncopyable_::noncopyable::noncopyable(const boost::noncopyable_::noncopyable&)’是私有的noncopyable( const noncopyable& );^
test.cpp:4:7: 錯誤:在此上下文中class A : boost::noncopyable {^
test.cpp: 在函數‘int main()’中:
test.cpp:14:9: 附注:在這里第一次需要生成的方法‘A::A(const A&)’A a3 = a1;^
4. conclusion
解決問題:不聲明copy構造或copy assignment操作符,編譯器可能自動生成,使class支持copying,但自聲明卻依舊使得支持copying
 解決方法:將兩者 聲明為private且不實現,阻止copying【private將鏈接期錯誤前移至編譯期】
 底層運行:客戶企圖拷貝,亦或member、friend函數調用拷貝,編譯器都將阻撓
 阻撓原因:因嘗試拷貝時,編譯器生成的copy構造或copy assignment操作符,被拒絕調用base class的對應兄弟【private】
noncopyable實現及運用 :
 ??1、不一定得public繼承noncopyable,可private繼承 【條款32 條款39】
 ??2、noncopyable析構不一定得是virtual 【條款7】
 ??3、noncopyable不含數據,符合空基類優化資格【條款39】
 ??4、作為基類,可能導致多繼承【條款 40】,阻止空基類優化
總結
以上是生活随笔為你收集整理的【Boost】noncopyable:不可拷贝的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: svo_note
- 下一篇: ubuntu clion 创建桌面快捷方
