C++ std :: unique_ptr但不可移动?

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)

Nev*_*vin 5

只需制作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)

  • [这不起作用。](http://coliru.stacked-crooked.com/a/003e7a49a4598802) 使类不可复制/不可移动并不意味着其成员不能移动。 (2认同)