C++ 如何知道是否移动了对象

C++ 如何知道是否移动了对象,c++,design-patterns,C++,Design Patterns,这可能是一个愚蠢的问题,但我觉得我错过了一些设计模式 在销毁一个类的过程中,如果它被移动或不被移动,我想做不同的操作。我考虑实现一个简单的布尔值,当类被移动时,它会被勾选 像这样: class A { A(A && a) { a.was_moved = true; } ~A() { do some stuff if (!was_moved) { clean some more stuff } bool

这可能是一个愚蠢的问题,但我觉得我错过了一些设计模式

在销毁一个类的过程中,如果它被移动或不被移动,我想做不同的操作。我考虑实现一个简单的布尔值,当类被移动时,它会被勾选

像这样:

class A {
    A(A && a) {
        a.was_moved = true;
    }

~A() {
    do some stuff

    if (!was_moved) {
        clean some more stuff
    }

bool was_moved = false;
};

有没有“更好”的方法?一些cpp特性我可以问这个类是被移动了还是一些已知的设计模式。

没有允许这样做的特性。但一般来说,你不需要知道这一点

通常,在定义移动构造函数时,您希望它将基础数据从一个对象“移动”到另一个对象。在您的上下文中,您似乎希望源对象在之后为“空”,以便只有一个所有者(毕竟它是“移动”,而不是“复制”)。因此,您真正需要的是对“空”对象的正确定义和处理该情况的正确方法

例如,假设您的类与文件描述符相关联。然后可以将默认值fd设置为-1,并在该值上区分析构函数:

#include <utility>

class A
{
    public:
        A(int fd) : fd { fd }
        {
        }

        A(A&& other) : fd { std::exchange(other.fd, -1) }
        {
        }

        ~A()
        {
            if (fd != -1)
            {
                close(fd);
            }
        }

    private:
        int fd = -1;
};
#包括
甲级
{
公众:
A(int-fd):fd{fd}
{
}
A(A&&other):fd{std::exchange(other.fd,-1)}
{
}
~A()
{
如果(fd!=-1)
{
关闭(fd);
}
}
私人:
int-fd=-1;
};

当然,您可以通过附加标志将对象标记为空。事实上,在某些特殊情况下,人们会这样做。甚至在标准库中。你可能想。请注意,
唯一锁定
类上的
\uuuuuuuuu拥有
标志。

没有允许这样做的功能。但一般来说,你不需要知道这一点

通常,在定义移动构造函数时,您希望它将基础数据从一个对象“移动”到另一个对象。在您的上下文中,您似乎希望源对象在之后为“空”,以便只有一个所有者(毕竟它是“移动”,而不是“复制”)。因此,您真正需要的是对“空”对象的正确定义和处理该情况的正确方法

例如,假设您的类与文件描述符相关联。然后可以将默认值fd设置为-1,并在该值上区分析构函数:

#include <utility>

class A
{
    public:
        A(int fd) : fd { fd }
        {
        }

        A(A&& other) : fd { std::exchange(other.fd, -1) }
        {
        }

        ~A()
        {
            if (fd != -1)
            {
                close(fd);
            }
        }

    private:
        int fd = -1;
};
#包括
甲级
{
公众:
A(int-fd):fd{fd}
{
}
A(A&&other):fd{std::exchange(other.fd,-1)}
{
}
~A()
{
如果(fd!=-1)
{
关闭(fd);
}
}
私人:
int-fd=-1;
};

当然,您可以通过附加标志将对象标记为空。事实上,在某些特殊情况下,人们会这样做。甚至在标准库中。你可能想。请注意,
唯一锁
类上的
\uuuuuuu拥有
标志。

没有标准方法知道它。但这很重要 定义移动构造函数和移动赋值,以便清理 执行移动前现有对象的资源:

class MoveDemo
{
    size_t size;
    char *buf;

    public:
    explicit MoveDemo(int sz=1024):size(sz), buf(new char[size]) {}
    ~MoveDemo { delete [] buf; }
    MoveDemo(MoveDemo&& other);
    MoveDemo& operator=(MoveDemo&& other);
};

MoveDemo::MoveDemo(MoveDemo&& other):size(0), buf(nullptr)
{
    size = other.size;
    buf = other.buf;

    //reset other
    other.size = 0;
    other.buf = nullptr;
}

MoveDemo& MoveDemo::operator=(MoveDemo&& other)
{
    if (this != &other)
    {
        // release current objects resources
        delete [] buf;
        size = 0;

        // move
        size = other.size;
        buf = other.buf;

        //reset other
        other.size = 0;
        other.buf = nullptr;
    }
    return *this;
}

没有标准的方法来了解它。但这很重要 定义移动构造函数和移动赋值,以便清理 执行移动前现有对象的资源:

class MoveDemo
{
    size_t size;
    char *buf;

    public:
    explicit MoveDemo(int sz=1024):size(sz), buf(new char[size]) {}
    ~MoveDemo { delete [] buf; }
    MoveDemo(MoveDemo&& other);
    MoveDemo& operator=(MoveDemo&& other);
};

MoveDemo::MoveDemo(MoveDemo&& other):size(0), buf(nullptr)
{
    size = other.size;
    buf = other.buf;

    //reset other
    other.size = 0;
    other.buf = nullptr;
}

MoveDemo& MoveDemo::operator=(MoveDemo&& other)
{
    if (this != &other)
    {
        // release current objects resources
        delete [] buf;
        size = 0;

        // move
        size = other.size;
        buf = other.buf;

        //reset other
        other.size = 0;
        other.buf = nullptr;
    }
    return *this;
}

为什么它是或不是很重要?通常你不需要移动对象,直到iw被完全销毁。与其检查
was\u moved
,只需为“空”对象定义好清理。不要只是拆开指针,而是将源指针设置为
nullptr
,诸如此类。为什么它是或不是很重要?通常你不需要移动对象,直到iw完全被销毁。与其检查
was\u moved
,不如为“空”对象定义好清理。不要只分解指针,而是将源指针设置为
nullptr
,等等。我建议使用。必须提供第二个参数不会让您忘记重置成员。不需要严格地将源对象设为空。任何国家都是有效的。这也意味着您可以实现作为交换的移动。@StoryTeller您的意思是
fd=std::exchange(other.fd,fd)?这是我第一次使用这个函数。@m通常你是对的。答案是OP问题的上下文,我假设这就是他要找的。@freakish-
fd=std::exchange(other.fd,-1)
。您甚至可以将分配转换为初始化。我建议使用。必须提供第二个参数不会让您忘记重置成员。不需要严格地将源对象设为空。任何国家都是有效的。这也意味着您可以实现作为交换的移动。@StoryTeller您的意思是
fd=std::exchange(other.fd,fd)?这是我第一次使用这个函数。@m通常你是对的。答案是OP问题的上下文,我假设这就是他要找的。@freakish-
fd=std::exchange(other.fd,-1)
。您甚至可以将赋值转换为初始化。