实现不可复制的C++类

Implementing a non-copyable C++ class

本文关键字:C++ 可复制 实现      更新时间:2023-10-16

在Visual Studio 2019中,我正在尝试实现使类不可复制的技术,以显示C++11,以及稍后在如何使这个C++对象不可复制?的接受答案。

我的班级是,

class Foo {
public:
Foo();
Foo(std::string name);
~Foo();
std::string m_name;
static std::int32_t s_counter;
public:
Foo(const Foo& inFoo) = delete;
Foo& operator=(const Foo& inFoo) = delete;
};

定义代码是,

std::int32_t Foo::s_counter = 0;
Foo::Foo(void)
{
Foo::s_counter++;
std::cout << "Foo constructor.  Count = " << Foo::s_counter << std::endl;
}
Foo::Foo(std::string name)
{
Foo::s_counter++;
m_name = name;
std::cout << "Foo " << m_name << " constructor.  Count = " << Foo::s_counter << std::endl;
}
Foo::~Foo()
{
Foo::s_counter--;
std::cout << "Foo destructor.  Count = " << Foo::s_counter << std::endl;
}

它用于,

int main(int argc, char** argv) {
std::vector<Foo> fooVector;
{
Foo myFoo1{ Foo() };
fooVector.push_back(std::move(myFoo1));
Foo myFoo2{ Foo("myFoo2") };
fooVector.push_back(std::move(myFoo2));
}
if (Foo::s_counter < 0) {
std::cout << "Foo object count = " << Foo::s_counter << std::endl;
}
std::cin.get();
}

其中我有意限定了myFoo1myFoo2的定义范围,以便获得对象计数反馈。

当复制构造函数和赋值构造函数public时,如图所示,编译错误是"C2280 'Foo::Foo(const Foo &(':尝试引用已删除的函数"。当它们成为私有时,编译错误是"C2248 'Foo::Foo':无法访问在类'Foo'中声明的私有成员"。

我相信我误解了原始 SO 答案中的某些内容,但我看不出它是什么。

一切都按预期工作。

您的代码尝试两个副本,并且您为使类不可复制而采用的两种方法都成功了。你可以看到这一点,因为你遇到了编译错误。

如果您不打算在此测试用例中尝试复制,则可能是以下行:

Foo myFoo1{ Foo() };
Foo myFoo2{ Foo("myFoo2") };

在 C++17 之前,这些是副本初始化。如果这不是您的意图,并且您是 C++17 岁之前,那么您应该将它们更改为:

Foo myFoo1{};
Foo myFoo2{"myFoo2"};

或者一个好的老式:

Foo myFoo1;
Foo myFoo2("myFoo2");

同时,你的push_back肯定是复制的,因为虽然你写了std::move,但你的类是不可移动的(没有移动构造函数(,所以std::move实际上什么都不做。

所以:

  1. 尝试复制对象
  2. 正在阻止复制

一切都是应该的。