C++的noncopyable是啥

简介

  就是一些类你不想让编译器生成默认的拷贝构造函数,目的是防止调用默认的拷贝构造出问题。

编译器生成的默认拷贝构造存在的隐患

// for_test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <boost/noncopyable.hpp>


class MyClass //: boost::noncopyable
{
public:
	MyClass() { m_data = new char('Y'); }
	~MyClass()
	{
		delete m_data;
	}
private:
	char * m_data;
};


int main()
{
	{
		MyClass classA;
		MyClass classB(classA);
	}
	/* 执行到这的时候,出了花括号,classA的析构函数被调用,classB的析构函数也被调用
	m_data被删除两次,就出错了。*/

    std::cout << "Hello World!\n";
}


  细心的小伙伴发现我没有定义拷贝赋值函数为啥赋值操作还能进行?实际上是编译器自动生成了。编译器也不是大聪明,只会进行简单的生成,对于结构复杂的类,如果我们没有定义合适的拷贝赋值或拷贝构造,就需要显示声明,后面的代码不能对该类的对象进行复制操作。

boost实现不可拷贝的方案

// for_test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <boost/noncopyable.hpp>


class MyClass : boost::noncopyable
{
public:
	MyClass() { m_data = new char('Y'); }
	~MyClass()
	{
		delete m_data;
	}
private:
	char * m_data;
};


int main()
{
	{
		MyClass classA;
		MyClass classB(classA);
	}
	/// 执行到这的时候,出了花括号,classA的析构函数被调用,classB的析构函数也被调用
	/// 成员m_data被删除两次,就出问题了。

    std::cout << "Hello World!\n";
}


用法很简单,继承boost::noncopyable类就行了。main里面的代码进行了复制,编译器就会报错:

严重性 代码 说明 项目 文件 行 禁止显示状态
错误(活动) E1776 无法引用 函数 “MyClass::MyClass(const MyClass &)” (已隐式声明) – 它是已删除的函数 for_test C:\Users\YK-067\source\repos\for_test\for_test.cpp 25
严重性 代码 说明 项目 文件 行 禁止显示状态
错误 C2280 “MyClass::MyClass(const MyClass &)”: 尝试引用已删除的函数 for_test C:\Users\YK-067\source\repos\for_test\for_test.cpp 25

boost源码

noncopyable.hpp

//  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 {

//  私有的拷贝构造和拷贝赋值使得子类的不可被复制

namespace noncopyable_  // protection from unintended ADL。ADL 实参依赖查找(argument-dependent lookup), 允许调用其他命名空间中的函数。
{
#ifndef BOOST_NONCOPYABLE_BASE_TOKEN_DEFINED
#define BOOST_NONCOPYABLE_BASE_TOKEN_DEFINED

// noncopyable derives from base_token to enable Type Traits to detect
// whether a type derives from noncopyable without needing the definition
// of noncopyable itself.
//
// The definition of base_token is macro-guarded so that Type Traits can
// define it locally without including this header, to avoid a dependency
// on Core.

  struct base_token {};

#endif // #ifndef BOOST_NONCOPYABLE_BASE_TOKEN_DEFINED

  class noncopyable: base_token
  {
  protected:
#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && !defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS)
      BOOST_CONSTEXPR noncopyable() = default;
      ~noncopyable() = default;
#else
      noncopyable() {}
      ~noncopyable() {}
#endif
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
      noncopyable( const noncopyable& ) = delete;
      noncopyable& operator=( const noncopyable& ) = delete;
#else
  private:  // emphasize the following members are private
      noncopyable( const noncopyable& );
      noncopyable& operator=( const noncopyable& );
#endif
  };
}

typedef noncopyable_::noncopyable noncopyable;

} // namespace boost

#endif  // BOOST_CORE_NONCOPYABLE_HPP

总结

  实际原理上很简单,就是父类把operator=()成员函数定义成private的了。
目的也很直白,就是该类的对象别给我拷来拷去。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值