为什么移动对象不让它为空?
Why doesn't moving an object leave it null?
A a5(move(a1));
虽然移动后 a1 的成员变量被设置为默认值,但 a1 本身并未设置为 null。您不能执行 a1 == nullptr... 来检查 a1 是否无用...
我觉得这很奇怪。我在这里有什么误解吗?我认为如果 a1 被移动,它就变得无用了,这应该通过以某种方式将它设置为 null 来表示。没有?
关键是让 a1 处于非空状态,它仍然可以使用。没有编译器警告或错误。没有真正的迹象表明该对象处于混乱状态。如果 a 有两个成员变量,一个 int 和一个动态 alloc 对象,则 dyn alloc 对象将指向 nullptr 但 int 将具有 def 值(当然只有在正确实现的情况下......容易搞砸)。
所以移动后你可以
int number = a1.getInt();
并取回一个数字,但没有意识到 a1 已被重置。在 C 和 C++ 中,我们被教导在其资源被窃取时将指针设置为空值(a.k.a nullptr 或 NULL)以消除此类混淆。随着移动窃取对象资源的引入,是否没有内置机制或最佳实践来指示对象已被窃取,从而使"reset"处于默认构造状态?
编辑
添加示例移动 c'tor
A(A&& other) : num(other.num), s(other.s){
other.num = 0;
other.s = nullptr; //dyn alloc obj
}
移动操作的结果应该使对象处于有效但未指定的状态。通常,如果您要销毁对象或为对象分配新值,您会移动。您通常不会在移出某个对象后尝试使用该对象。
a1
类型的 move-constructor 负责执行移动并使对象处于您希望的状态。 如果 default-generated 移动构造函数的行为不符合您的意愿,那么您可以为该对象编写自己的移动构造函数。例如,您可以在此移动构造函数中将指针设置为 null。或者您可以设置一个标志,指示对象处于 moved-from 状态。
在您的问题中,您 "wish for" 的行为更像是与空对象交换的行为。也许以下代码更适合您:
A a5{};
using std::swap;
swap(a5, a1);
关于建议 other.s
指向 "dyn alloc obj" 的更新:您应该避免这样做,因为这意味着您必须浪费时间编写 copy-constructor、move-constructor 、copy-assignment 运算符、move-assignment 运算符和析构函数。
你是你自己死亡的建筑师:通过将这个指针引入你的 class 你制造了你正在抱怨的确切的移动问题。
相反,任何拥有的资源都应由其自己的 class 管理。标准库的 std::unique_ptr
足以满足许多此类用例。
Why doesn't moving an object leave it null?
因为如果对象不是指针,那么它一般不会有"null state",所以你不能"leave it null";如果它是一个指针,当你从它 "move" 时你不会把它设为 null。
Leaving a1 in a non null state, it still can be used. There is no compiler warning or error. There is no real indication that the object is in a messed up state...
它不处于 messed-up 状态,它处于 valid state 状态。但是,当您使用 moved-from 对象的 post-move 值时发出警告也许不是一个坏主意。
A a5(move(a1));
虽然移动后 a1 的成员变量被设置为默认值,但 a1 本身并未设置为 null。您不能执行 a1 == nullptr... 来检查 a1 是否无用...
我觉得这很奇怪。我在这里有什么误解吗?我认为如果 a1 被移动,它就变得无用了,这应该通过以某种方式将它设置为 null 来表示。没有?
关键是让 a1 处于非空状态,它仍然可以使用。没有编译器警告或错误。没有真正的迹象表明该对象处于混乱状态。如果 a 有两个成员变量,一个 int 和一个动态 alloc 对象,则 dyn alloc 对象将指向 nullptr 但 int 将具有 def 值(当然只有在正确实现的情况下......容易搞砸)。
所以移动后你可以
int number = a1.getInt();
并取回一个数字,但没有意识到 a1 已被重置。在 C 和 C++ 中,我们被教导在其资源被窃取时将指针设置为空值(a.k.a nullptr 或 NULL)以消除此类混淆。随着移动窃取对象资源的引入,是否没有内置机制或最佳实践来指示对象已被窃取,从而使"reset"处于默认构造状态?
编辑 添加示例移动 c'tor
A(A&& other) : num(other.num), s(other.s){
other.num = 0;
other.s = nullptr; //dyn alloc obj
}
移动操作的结果应该使对象处于有效但未指定的状态。通常,如果您要销毁对象或为对象分配新值,您会移动。您通常不会在移出某个对象后尝试使用该对象。
a1
类型的 move-constructor 负责执行移动并使对象处于您希望的状态。 如果 default-generated 移动构造函数的行为不符合您的意愿,那么您可以为该对象编写自己的移动构造函数。例如,您可以在此移动构造函数中将指针设置为 null。或者您可以设置一个标志,指示对象处于 moved-from 状态。
在您的问题中,您 "wish for" 的行为更像是与空对象交换的行为。也许以下代码更适合您:
A a5{};
using std::swap;
swap(a5, a1);
关于建议 other.s
指向 "dyn alloc obj" 的更新:您应该避免这样做,因为这意味着您必须浪费时间编写 copy-constructor、move-constructor 、copy-assignment 运算符、move-assignment 运算符和析构函数。
你是你自己死亡的建筑师:通过将这个指针引入你的 class 你制造了你正在抱怨的确切的移动问题。
相反,任何拥有的资源都应由其自己的 class 管理。标准库的 std::unique_ptr
足以满足许多此类用例。
Why doesn't moving an object leave it null?
因为如果对象不是指针,那么它一般不会有"null state",所以你不能"leave it null";如果它是一个指针,当你从它 "move" 时你不会把它设为 null。
Leaving a1 in a non null state, it still can be used. There is no compiler warning or error. There is no real indication that the object is in a messed up state...
它不处于 messed-up 状态,它处于 valid state 状态。但是,当您使用 moved-from 对象的 post-move 值时发出警告也许不是一个坏主意。