San*_*lin 2 c++ unique-ptr c++11
我正在使用std :: unique_ptr在类上创建一些公共成员,这些成员必须是不可复制的或可移动的.但是std :: unique_ptr是可移动的,我想知道如果有人移动std :: unique_ptr包含的指针然后我尝试访问被移动的那个类的std :: unique_ptr成员会发生什么.
示例代码:
#include <cstdlib>
#include <memory>
#include <string>
#include <iostream>
struct obj
{
obj(std::string id)
: id(id)
{
}
void identif()
{
std::cout << "i am " << id << std::endl;
}
std::string id;
};
struct objs
{
// They must stay here no mater what.
std::unique_ptr< obj > obj_a;
std::unique_ptr< obj > obj_b;
std::unique_ptr< obj > obj_c;
objs()
: obj_a(std::unique_ptr< obj >( new obj("object a") ))
,obj_b(std::unique_ptr< obj >( new obj("object b") ))
,obj_c(std::unique_ptr< obj >( new obj("object c") ))
{
}
void do_a()
{
std::cout << " member: " << obj_a->id << std::endl;
std::cout << " method: ";
obj_a->identif();
}
void do_b()
{
std::cout << " member: " << obj_b->id << std::endl;
std::cout << " method: ";
obj_b->identif();
}
void do_c()
{
std::cout << " member: " << obj_c->id << std::endl;
std::cout << " method: ";
obj_c->identif();
}
};
int main(int argc, char** argv)
{
objs obx;
std::cout << " before move: " << std::endl;
obx.do_a();
obx.do_b();
obx.do_c();
std::cout << " after move: " << std::endl;
std::unique_ptr< obj > newb(std::move(obx.obj_b));
obx.do_a();
obx.do_b();
obx.do_c();
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
应用程序崩溃,因为当然导致我的问题.我怎样才能防范这种情况?
对象必须是公共的,不是常量,不能移动或复制.有问题的实际对象使用可变参数模板,我宁愿不使用旧方法在obj中使用静态成员函数create(),然后保护构造函数.此外,我需要避免geters和setter,因为该类使用可变参数模板,并使代码丑陋.
我所需要的只是使std :: unique_ptr不可移动,并简单地保存一个不能从拥有它的类中移动或复制的唯一指针.
实际的代码是来自Nano-signal-slot库的Nano :: signal类.(如果有人需要实际代码)
编辑:适应使用Nevin的方法并使其工作.我发布了代码,因为Nevin在容器而不是对象上实现它.
#include <cstdlib>
#include <memory>
#include <string>
#include <iostream>
struct obj
{
obj(std::string id)
: id(id)
{
}
obj(obj const&) = delete;
obj& operator=(obj const&) = delete;
obj& operator=(obj&&) = delete;
obj(obj&&) = delete;
void identif()
{
std::cout << "i am " << id << std::endl;
}
std::string id;
};
struct objs
{
const std::unique_ptr< obj > obj_a;
const std::unique_ptr< obj > obj_b;
const std::unique_ptr< obj > obj_c;
objs()
: obj_a(std::unique_ptr< obj >( new obj("object a") ))
,obj_b(std::unique_ptr< obj >( new obj("object b") ))
,obj_c(std::unique_ptr< obj >( new obj("object c") ))
{
}
void do_a()
{
std::cout << " member: " << obj_a->id << std::endl;
std::cout << " method: ";
obj_a->identif();
}
void do_b()
{
std::cout << " member: " << obj_b->id << std::endl;
std::cout << " method: ";
obj_b->identif();
}
void do_c()
{
std::cout << " member: " << obj_c->id << std::endl;
std::cout << " method: ";
obj_c->identif();
}
};
int main(int argc, char** argv)
{
objs obx;
std::cout << " before move: " << std::endl;
obx.do_a();
obx.do_b();
obx.do_c();
std::cout << " after move: " << std::endl;
std::unique_ptr< obj > newb(std::move(obx.obj_b));
obx.do_a();
obx.do_b();
obx.do_c();
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
这应该现在生成:
main.cpp: In function 'int main(int, char**)':
main.cpp:77:53: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = obj; _Dp = std::default_delete<obj>]'
std::unique_ptr< obj > newb(std::move(obx.obj_b));
^
In file included from /usr/include/c++/4.8/memory:81:0,
from main.cpp:2:
/usr/include/c++/4.8/bits/unique_ptr.h:273:7: error: declared here
unique_ptr(const unique_ptr&) = delete;
^
Run Code Online (Sandbox Code Playgroud)
只需制作objs不可复制和不可移动的内容,如:
struct objs
{
objs(objs const&) = delete;
objs& operator=(objs const&) = delete;
objs& operator=(objs&&) = delete;
objs(objs&&) = delete;
std::unique_ptr< obj > obj_a;
std::unique_ptr< obj > obj_b;
std::unique_ptr< obj > obj_c;
objs()
: obj_a(std::unique_ptr< obj >( new obj("object a") ))
,obj_b(std::unique_ptr< obj >( new obj("object b") ))
,obj_c(std::unique_ptr< obj >( new obj("object c") ))
{}
};
Run Code Online (Sandbox Code Playgroud)
另外,一旦你完成了这项工作,内部也不需要指针.您可以将代码简化为:
struct objs
{
objs(objs const&) = delete;
objs& operator=(objs const&) = delete;
objs& operator=(objs&&) = delete;
objs(objs&&) = delete;
obj obj_a;
obj obj_b;
obj obj_c;
objs()
: obj_a("object a")
,obj_b("object b")
,obj_c("object c")
{}
};
Run Code Online (Sandbox Code Playgroud)