在 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;
};
Run Code Online (Sandbox Code Playgroud)
定义代码是,
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;
}
Run Code Online (Sandbox Code Playgroud)
它用于,
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();
}
Run Code Online (Sandbox Code Playgroud)
其中我有意限定了myFoo1and的定义,myFoo2以便获得对象计数反馈。
当创建复制构造函数和赋值构造函数时public,如图所示,编译错误是“C2280 'Foo::Foo(const Foo &)': 试图引用已删除的函数”。将它们设为私有时,编译错误为“C2248 'Foo::Foo': 无法访问类 'Foo' 中声明的私有成员”。
我相信我误解了原始 SO 答案中的某些内容,但我看不到它是什么。
一切都按预期工作。
您的代码尝试了两个副本,并且您使类不可复制的两种方法都成功了。您可以看到,因为您遇到了编译错误。
如果您不打算在此测试用例中尝试复制,则可能是以下几行:
Foo myFoo1{ Foo() };
Foo myFoo2{ Foo("myFoo2") };
Run Code Online (Sandbox Code Playgroud)
在 C++17 之前,那些是复制初始化。如果这不是您想要的,并且您是 C++17 之前的,那么您应该将它们更改为:
Foo myFoo1{};
Foo myFoo2{"myFoo2"};
Run Code Online (Sandbox Code Playgroud)
......或者一个很好的老式:
Foo myFoo1;
Foo myFoo2("myFoo2");
Run Code Online (Sandbox Code Playgroud)
同时,您的push_backs 绝对是副本,因为尽管您编写了 ,但您std::move的类不可移动(没有移动构造函数),因此std::move实际上什么也不做。
所以:
一切都应该如此。