使用宏覆盖类移动函数接口的缺点
Disadvantage of using macro to cover interface of move-like function
使用宏作为所有移动语义的接口有什么缺点?
我最近阅读了 class ( ) 中与移动相关的函数的语法,在我看来,它非常乏味和重复:-
C(C&&) = default; // Move constructor
C& operator=(C&&) & = default; // Move assignment operator
如果我想用相同的实现自定义移动赋值和移动构造函数,那就更麻烦了。 (与 Copy constructor and = operator overload in C++: is a common function possible? 相同的问题)
因此,我决定创建一个宏(类似交换的函数),使所有内容都简洁地放在一个地方。
#define MACRO_MOVE(C) \
C& operator=(C&& that) & { \
moveHack(this,&that); return *this; \
} \
C(C&& that){ \
moveHack(this,&that); \
} \
static void moveHack(C* dst,C* src)
这是用法:-
class X{
int data=42;
MACRO_MOVE(X){
dst->data=src->data;
src->data=0;
}
};
不过,我还没有见过有人这样做过。
有什么我应该关注的问题吗?
这种方法有什么具体的缺点吗?
零规则是只有 类 管理资源(如内存)需要显式 move/copy assign/construction 方法。
您可以将几乎所有类型的存储组合成自我管理的资源。这些资源类型往往是几种不同变体之一(值指针、唯一指针、共享指针等)。
通常在移动分配时,您还希望清理现有状态。移动构建时情况并非如此。这两个实现 可以 共享一些代码,但通常您不希望它们共享。
对一些简单的资源管理类型进行这种宏黑客操作不是一个好主意。到处都有复杂的资源管理类型不是一个好主意。这个宏 hackery 不处理移动和分配是根本不同的操作。一般来说,只有在避免使用宏的成本很高时才应使用它。
您的宏没有增加多少实用性。它所做的看起来容易出错且危险。如果你必须调试它,你会得到不可调试的代码。
所以不使用该宏的原因有很多,而使用它的原因很少。
构造、赋值和销毁是联系在一起的。赋值可以天真地看成是破坏+构造,但通常效率低下;而你的连破坏都不做!
使用宏作为所有移动语义的接口有什么缺点?
我最近阅读了 class ( ) 中与移动相关的函数的语法,在我看来,它非常乏味和重复:-
C(C&&) = default; // Move constructor
C& operator=(C&&) & = default; // Move assignment operator
如果我想用相同的实现自定义移动赋值和移动构造函数,那就更麻烦了。 (与 Copy constructor and = operator overload in C++: is a common function possible? 相同的问题)
因此,我决定创建一个宏(类似交换的函数),使所有内容都简洁地放在一个地方。
#define MACRO_MOVE(C) \
C& operator=(C&& that) & { \
moveHack(this,&that); return *this; \
} \
C(C&& that){ \
moveHack(this,&that); \
} \
static void moveHack(C* dst,C* src)
这是用法:-
class X{
int data=42;
MACRO_MOVE(X){
dst->data=src->data;
src->data=0;
}
};
不过,我还没有见过有人这样做过。
有什么我应该关注的问题吗?
这种方法有什么具体的缺点吗?
零规则是只有 类 管理资源(如内存)需要显式 move/copy assign/construction 方法。
您可以将几乎所有类型的存储组合成自我管理的资源。这些资源类型往往是几种不同变体之一(值指针、唯一指针、共享指针等)。
通常在移动分配时,您还希望清理现有状态。移动构建时情况并非如此。这两个实现 可以 共享一些代码,但通常您不希望它们共享。
对一些简单的资源管理类型进行这种宏黑客操作不是一个好主意。到处都有复杂的资源管理类型不是一个好主意。这个宏 hackery 不处理移动和分配是根本不同的操作。一般来说,只有在避免使用宏的成本很高时才应使用它。
您的宏没有增加多少实用性。它所做的看起来容易出错且危险。如果你必须调试它,你会得到不可调试的代码。
所以不使用该宏的原因有很多,而使用它的原因很少。
构造、赋值和销毁是联系在一起的。赋值可以天真地看成是破坏+构造,但通常效率低下;而你的连破坏都不做!