当前位置: 代码迷 >> 综合 >> Boost(4):boost::noncopyable类详解
  详细解决方案

Boost(4):boost::noncopyable类详解

热度:60   发布时间:2023-12-08 21:47:08.0

1. 说明

在上一篇的示例中在说明封装抽象类时有用到boost::noncopyable类,在实际使用的很多情况下,加没加这个类似乎对我的操作没有影响,那么这个类到底有什么作用呢,在这篇笔记中详细分析一下。

1.1 noncopyable作用

其官方说明是:Private copy constructor and copy assignment ensure classes derived from class noncopyable cannot be copied.大意是将私有化类的拷贝构造函数和拷贝赋值操作符,这样子类可以调用,但是外部调用者不能通过复制/赋值等语句来产生一个新的对象。

boost::noncopyable主要的用法是作为父类供其他类继承其特性。

2. 示例

这里定义了两个类Test1和Test2,其中Test2继承boost::noncopyable的特性

#include <iostream>#include <boost/noncopyable.hpp>class Test1 {
    public:Test1(int i) {
    std::cout << "This is Test1 that is copyable" << std::endl;}
};class Test2 : boost::noncopyable {
    public:Test2(int i) {
    std::cout << "This is Test2 that is noncopyable" << std::endl;}
};int main()
{
    Test1 t1(1);Test2 t2(2);Test1 t3 = t1;    // It's OKTest1 t4(t1);     // It's OKTest2 t5 = t2;    // Cannot be referencedTest2 t6(t2);     // Cannot be referencedTest2 &t7 = t2;   // It's OKreturn 0;
}

直接编译时会报错,如下:

g++ test.cpptest.cpp: In function ‘int main()’:
test.cpp:23:16: error: use of deleted function ‘Test2::Test2(const Test2&)’23 |     Test2 t5 = t2;    // Cannot be referenced|                ^~
test.cpp:10:7: note: ‘Test2::Test2(const Test2&)’ is implicitly deleted because the default definition would be ill-formed:10 | class Test2 : boost::noncopyable {
    |       ^~~~~
test.cpp:10:7: error: use of deleted function ‘boost::noncopyable_::noncopyable::noncopyable(const boost::noncopyable_::noncopyable&)’
In file included from /usr/local/include/boost/noncopyable.hpp:15,from test.cpp:3:
/usr/local/include/boost/core/noncopyable.hpp:49:7: note: declared here49 |       noncopyable( const noncopyable& ) = delete;|       ^~~~~~~~~~~
test.cpp:24:16: error: use of deleted function ‘Test2::Test2(const Test2&)’24 |     Test2 t6(t2);     // Cannot be referenced

从编译信息可以看出,Test2不支持使用复制的方式来实例化类。

3. boost::noncopyable类详解

boost::noncopyable定义在 <boost/core/noncopyable.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
{
    
#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 Trais can
// define it locally without including this header, to avoid a dependency
// on Core.struct base_token {
    };#endif // #ifndef BOOST_NONCOPYABLE_BASE_TOKEN_DEFINEDclass 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;
#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

注意其中的关键语句:

#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

BOOST_NO_CXX11_DELETED_FUNCTIONS类重载了复制和"=“运算符,将它们变为"delete”。上面的语句中如果没有定义BOOST_NO_CXX11_DELETED_FUNCTIONS类,那么直接实现了重载运算符的功能,如果有定义,则将这两个运算符变成私有成员。即无论如何,noncopyable类下复制和"="运算符都被重载为"delete"了。

参考资料

https://www.boost.org/doc/libs/1_78_0/libs/core/doc/html/core/noncopyable.html