初始化列表和 std::forward

Initialization lists and std::forward

本文关键字:forward std 列表 初始化      更新时间:2023-10-16

我假设的对吗

class D { /* ... */ };
int f (const D & t) { return /* something calculated from t */; }
template<class T>
class C {
private:
    int m_i;
    T m_t;
    // or first m_t, then m_i -- careless order of declarations
public:
    template<class T_>
    C (T_ && t) : m_t (std::forward<T_> (t)), m_i (f (t)) {
    }
};
C<D> c (D ());

可能会导致错误,因为在调用f(t)t的值已被移走?除了 (i) 使用工厂函数或 (ii) 引入对声明m_im_t顺序的依赖之外,是否有任何方法可以避免此问题?

第一件事是初始值设定项列表的计算顺序由类定义中成员的顺序决定,因此在您的情况下,它将是:

template<class T_>
C (T_ && t) 
  : m_i (f (t)), m_t (std::forward<T_> (t)) {
}

所以在你的情况下很好。如果对成员重新排序,以便在m_i之前声明m_t并在初始化中使用m_t,也可以:

T m_t;
int m_i;
template<class T_>
C (T_ && t) 
  : m_t (std::forward<T_> (t)), m_i (f (m_t))  {
}
首先

初始化成员m_i,到值显然不会移动也不会移动时。当你初始化m_t(std::forward<T>(t))时,你隐含地承诺你不会使用t的值(至少,在你给它一个新的值之前)。

通常,执行顺序很重要,成员初始值设定项列表也是如此。也就是说,在成员之间引入依赖关系时,需要注意声明成员的顺序。