繁体   English   中英

std :: move在类模板中的构造函数初始化列表中

[英]std::move in constructor initializer list in class template

我有这样的模板:

template<typename T>
struct foo {
  T m_t;
  foo(T t) : m_t(t) {}
};

问题是,我想支持小/普通类型和巨大的类型(如矩阵)的T 您是否建议我像这样编写构造函数初始化列表

foo (T t) : m_t(std::move(t)) {}

并要求T型始终支持移动结构,即使是较小的类型? 还有更好的方法吗?

并要求T型始终支持移动结构,即使是较小的类型?

任何可复制构造的类型也可移动构造。 在这些情况下移动只需调用复制构造函数。 因此,没有理由使用m_t(std::move(t))

另一种方法是使用引用:

foo (T const& t) : m_t(t) {}
foo (T&& t) : m_t(std::move(t)) {}

这样做的好处是只涉及一种结构而不是两种结构。

是的,在这种情况下使用此举并没有不利之处。 所有可复制对象都可以自动移动,因此无关紧要。 事实上,有些人建议在可能的情况下始终移动变量,甚至是整数。

作为替代方案,您可以考虑使用完美转发,如本答案中所述

template <typename T2>
foo(T2&& t) : m_t(std::forward<T2>(t)) {}

如果你知道T定义了一个快速移动构造函数,那应该没关系。 否则,建议提供构造函数foo(const T&)以避免不必要的副本。

完美转发只是实现这一目标的一种技术。 Pubby写出构造函数foo(const T&)foo(T&&)的解决方案当然也没问题。 结果是一样的,它主要是风格问题。

您还询问了小整数类型。 理论上,通过引用传递它们比复制它们要慢,但无论如何编译器应该能够将它优化为副本。 我不认为它会有所作为。

因此,更好地优化T可能很大并且不提供快速移动构造函数的最坏情况。 通过引用传递最适合这种情况,并且通常也不应该是一个糟糕的选择。

通过值传递的优点是只有一个构造函数(没有模板),但与上述替代方案相比,其代价是一个额外的移动构造。

但是,Pubby给出了pass-by-value和非模板解决方案的另一个未提及的缺点:如果复制构造函数定义为T(T&);则移动将不起作用T(T&); (注意对非const的引用)。 Rvalue-references可以绑定到lvalue-references-to-const,但不能绑定到lvalue-references-to-non-const,因此编译器无法调用复制构造函数。

要解决此问题,您只需向Pubby的解决方案添加第三个重载foo (T & t) : m_t(t) {}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM