constexpr 移动构造函数是否有意义?
Does a constexpr move constructor ever make sense?
constexpr
移动构造函数有意义吗?
例如,考虑以下内容:
#include <array>
class C
{
public:
constexpr C(std::array<int, 3> ar) : m_ar{ar} {}
constexpr C(C&& other) : m_ar{std::move(other.m_ar)} { }
private:
std::array<int, 3> m_ar;
};
int main()
{
constexpr C c1 {{{1, 2, 3}}};
constexpr C c2{std::move(c1)};
return 0;
}
这不会编译,因为尽管在 c1
上调用 std::move
,编译器推断它需要使用(隐式删除的)复制构造函数,而不是移动构造函数。我不知道为什么。
但是如果我从 c1
中删除 constexpr
,那么 constexpr
移动构造函数将无法使用它。
有什么方法可以让它发挥作用吗?或者这对于 constexpr
移动构造函数来说是一个不好的例子,但有很好的例子吗?或者,使用 constexpr
移动构造函数总是错误的吗?
This doesn't compile, since despite calling std::move
on c1
, the compiler deduces it needs to use the (implicitly deleted) copy constructor
c1
是 C const
类型。当你 move()
它时,这实际上是对右值引用的强制转换,所以你得到 C const&&
。请注意,它仍然是 const
。当我们进行重载决议时,有三个构造函数:
C(std::array<int, 3> ); // not viable
C(C&& ); // not viable
C(C const& ) = delete; // viable!
C const&&
无法绑定到 C&&
,原因与 C const&
无法绑定到 C&
的原因相同。我们只剩下复制构造函数,它被隐式删除了。
拥有一个 constexpr 移动构造函数可能有意义 - 但您 "moving" 来自的对象无法真正移动,因为它可能是 const
。您可以添加一个 const
移动构造函数:
constexpr C(C const&& other) : m_ar(other.m_ar) { }
这是一个美化的复制构造函数,但它允许使用您想要的语法。也可以只允许复制。
原则上,移动构造函数可以与非const
对象一起使用,该对象的生命周期在常量表达式的计算期间开始:
// C++14
constexpr int f() {
C a(/* ... */);
C b = std::move(a);
return 0;
}
constexpr int i = f();
类似的事情可以在 C++11 中完成,例如
constexpr C foo(C&& c) {
return std::move(c);
}
constexpr int f() {
return foo(C()), 0;
}
也就是说,由于常量表达式中使用的所有内容都必须是微不足道的可破坏的,因此移动构造函数的用处相当有限。
constexpr
移动构造函数有意义吗?
例如,考虑以下内容:
#include <array>
class C
{
public:
constexpr C(std::array<int, 3> ar) : m_ar{ar} {}
constexpr C(C&& other) : m_ar{std::move(other.m_ar)} { }
private:
std::array<int, 3> m_ar;
};
int main()
{
constexpr C c1 {{{1, 2, 3}}};
constexpr C c2{std::move(c1)};
return 0;
}
这不会编译,因为尽管在 c1
上调用 std::move
,编译器推断它需要使用(隐式删除的)复制构造函数,而不是移动构造函数。我不知道为什么。
但是如果我从 c1
中删除 constexpr
,那么 constexpr
移动构造函数将无法使用它。
有什么方法可以让它发挥作用吗?或者这对于 constexpr
移动构造函数来说是一个不好的例子,但有很好的例子吗?或者,使用 constexpr
移动构造函数总是错误的吗?
This doesn't compile, since despite calling
std::move
onc1
, the compiler deduces it needs to use the (implicitly deleted) copy constructor
c1
是 C const
类型。当你 move()
它时,这实际上是对右值引用的强制转换,所以你得到 C const&&
。请注意,它仍然是 const
。当我们进行重载决议时,有三个构造函数:
C(std::array<int, 3> ); // not viable
C(C&& ); // not viable
C(C const& ) = delete; // viable!
C const&&
无法绑定到 C&&
,原因与 C const&
无法绑定到 C&
的原因相同。我们只剩下复制构造函数,它被隐式删除了。
拥有一个 constexpr 移动构造函数可能有意义 - 但您 "moving" 来自的对象无法真正移动,因为它可能是 const
。您可以添加一个 const
移动构造函数:
constexpr C(C const&& other) : m_ar(other.m_ar) { }
这是一个美化的复制构造函数,但它允许使用您想要的语法。也可以只允许复制。
原则上,移动构造函数可以与非const
对象一起使用,该对象的生命周期在常量表达式的计算期间开始:
// C++14
constexpr int f() {
C a(/* ... */);
C b = std::move(a);
return 0;
}
constexpr int i = f();
类似的事情可以在 C++11 中完成,例如
constexpr C foo(C&& c) {
return std::move(c);
}
constexpr int f() {
return foo(C()), 0;
}
也就是说,由于常量表达式中使用的所有内容都必须是微不足道的可破坏的,因此移动构造函数的用处相当有限。