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)
。您甚至可以将赋值转换为初始化。