相关疑难解决方法(0)

何时使用std :: forward来转发参数?

C++ 0x显示了一个使用示例std::forward:

template<class T>
void foo(T&& arg) 
{
  bar(std::forward<T>(arg));
}
Run Code Online (Sandbox Code Playgroud)

什么时候使用它std::forward总是有利的?

另外,它需要&&在参数声明中使用,它在所有情况下都有效吗?如果函数在其中声明,我认为你必须将临时函数传递给函数&&,那么可以使用任何参数调用foo吗?

最后,如果我有一个函数调用,如下所示:

template<int val, typename... Params>
void doSomething(Params... args) {
  doSomethingElse<val, Params...>(args...);
}
Run Code Online (Sandbox Code Playgroud)

我应该用它代替:

template<int val, typename... Params>
void doSomething(Params&&... args) {
  doSomethingElse<val, Params...>(std::forward<Params>(args)...);
}
Run Code Online (Sandbox Code Playgroud)

另外,如果在函数中使用两次参数,即同时转发到两个函数,是否明智使用std::forward?不会std::forward将相同的东西转换为临时两次,移动内存并使其无效以供第二次使用?以下代码是否可以:

template<int val, typename... Params>
void doSomething(Params&&... args) {
  doSomethingElse<val, Params...>(std::forward<Params>(args)...);
  doSomethingWeird<val, Params...>(std::forward<Params>(args)...);
}
Run Code Online (Sandbox Code Playgroud)

我有点困惑std::forward,我很乐意使用一些清理工作.

c++ templates forwarding c++11

150
推荐指数
2
解决办法
5万
查看次数

移动物体怎么办?

标准是否准确定义了对象移动后我可以对其做什么?我曾经认为你用移动物体做的所有事情都可以破坏它,但这还不够.

例如,采用swap标准库中定义的函数模板:

template <typename T>
void swap(T& a, T& b)
{
    T c = std::move(a); // line 1
    a = std::move(b);   // line 2: assignment to moved-from object!
    b = std::move(c);   // line 3: assignment to moved-from object!
}
Run Code Online (Sandbox Code Playgroud)

显然,必须可以分配给移动的对象,否则第2行和第3行将失败.那么移动对象我还能做些什么呢?我在哪里可以找到标准中的这些细节?

(顺便说一句,为什么它T c = std::move(a);不是T c(std::move(a));第1行呢?)

c++ swap variable-assignment move-semantics c++11

136
推荐指数
2
解决办法
1万
查看次数

std :: forward如何工作?

可能重复:
使用forward的优点

我知道它的作用以及何时使用它但我仍然无法理解其工作原理.请尽可能详细,并解释std::forward如果允许使用模板参数推断,何时不正确.

我的一部分困惑是:"如果它有一个名字,它就是一个左值" - 如果是这样的话,为什么std::forward当我通过thing&& xvs 时表现不同thing& x

c++ c++11

106
推荐指数
2
解决办法
7万
查看次数

使用std :: forward vs std :: move

我一直认为std::forward这只适用于模板参数.但是,我问自己为什么.请参阅以下示例:

void ImageView::setImage(const Image& image){
    _image = image;
}

void ImageView::setImage(Image&& image){
    _image = std::move(image);
}
Run Code Online (Sandbox Code Playgroud)

这两个功能基本上是一样的; 一个采用l值参考,另一个采用r值参考.现在,我认为,std::forward如果参数是l值引用,则应返回l值引用,如果参数为1,则应返回r值引用,此代码可简化为如下所示:

void ImageView::setImage(Image&& image){
    _image = std::forward(image);
}
Run Code Online (Sandbox Code Playgroud)

这类似于cplusplus.com提到的示例std::forward(只是没有任何模板参数).我想知道,如果这是正确与否,如果不是为什么.

我也问自己究竟会有什么区别

void ImageView::setImage(Image& image){
    _image = std::forward(image);
}
Run Code Online (Sandbox Code Playgroud)

c++ move forward c++11

53
推荐指数
3
解决办法
2万
查看次数

为什么使用std :: forward <T>而不是static_cast <T &&>

当给出以下结构的代码时

template <typename... Args>
void foo(Args&&... args) { ... }
Run Code Online (Sandbox Code Playgroud)

我经常static_cast<Args&&>在函数中看到库代码用于参数转发.通常,对此的理由是使用static_cast避免不必要的模板实例化.

鉴于语言的参考折叠和模板扣除规则.我们得到了完美的转发,static_cast<Args&&>这个声明的证据如下(在误差范围内,我希望答案会启发)

  • 当给出rvalue引用时(或者为了完整性 - 没有像本示例中那样的引用限定条件),这会以这样的方式折叠引用,即结果是rvalue.使用的规则是&& &&- > &&(1上面的规则)
  • 当给定左值引用时,这会以这样的方式折叠引用,即结果是左值.这里使用的规则是& &&- > &(2上面的规则)

这基本上foo()bar()在上面的例子中转发参数.这也是你在std::forward<Args>这里使用时会得到的行为.


问题 -为什么要std::forward在这些背景下使用?避免额外的实例化是否有理由违反惯例?

Howard Hinnant的论文n2951规定了6个约束,在这些约束条件下,任何实现都std::forward应该"正确".这些曾经是

  1. 应该将左值作为左值转发
  2. 应该将右值作为右值转发
  3. 不应该将右值作为左值转发
  4. 应该将更少的cv限定表达式转发给更多cv限定的表达式
  5. 应该将派生类型的表达式转发为可访问的,明确的基类型
  6. 不应转发任意类型的转换

(1)和(2)证明与static_cast<Args&&>上述方法一起正常工作.(3) - (6)这里不适用,因为在推导的上下文中调用函数时,这些都不会发生.


注意:我个人更喜欢使用std::forward,但我的理由纯粹是我更喜欢坚持惯例.

c++ templates forwarding rvalue-reference c++17

23
推荐指数
3
解决办法
1429
查看次数

移动构造函数调用基类Move Constructor

我有一个基类,它基本上将一个类附加到任意窗口句柄(例如,HWND,HFONT),并使用策略类来附加/分离和销毁:

// class SmartHandle
template<typename THANDLE, class TWRAPPER, class TPOLICY>
class SmartHandle : boost::noncopyable
{
private:
    TPOLICY*  m_pPolicy;    // Policy
    bool m_bIsTemporary;    // Is this a temporary window?

    SmartHandle();  // no default ctor
    SmartHandle(const SmartHandle<THANDLE, TWRAPPER, TPOLICY>&);    // no cctor
protected:
    THANDLE   m_hHandle;    // Handle to the underlying window

    TPOLICY& policy() {return(*m_pPolicy);};

    // ctor that attaches but is temporary
    SmartHandle(const THANDLE& _handle, bool _temporary) : m_hHandle(_handle)
                                                         , m_bIsTemporary(_temporary)
    {
        m_pPolicy = new TPOLICY(reinterpret_cast<TWRAPPER&>(*this));
        if(_handle)
            m_pPolicy->attach(_handle);
    };  // eo ctor

    // …
Run Code Online (Sandbox Code Playgroud)

c++ templates move-constructor c++11

14
推荐指数
3
解决办法
6532
查看次数

std :: forward没有完美的转发?

建议std::forward通常仅限于完美转发函数模板参数的规范用例; 一些评论员甚至说这是唯一有效的用途std::forward.但考虑这样的代码:

// Temporarily holds a value of type T, which may be a reference or ordinary
// copyable/movable value.
template <typename T>
class ValueHolder {
 public:
  ValueHolder(T value)
    : value_(std::forward<T>(value)) {
  }


  T Release() {
    T result = std::forward<T>(value_);
    return result;
  }

 private:
  ~ValueHolder() {}

  T value_;
};
Run Code Online (Sandbox Code Playgroud)

在这种情况下,不会出现完美转发的问题:由于这是一个类模板而不是一个函数模板,客户端代码必须明确指定T,并可以选择是否以及如何对其进行ref-qualify.出于同样的原因,论证std::forward不是"普遍参考".

尽管如此,这std::forward似乎是一个很好的选择:我们不能把它排除在外,因为当它T是一个只移动类型时它不起作用,我们不能使用std::move它,因为当它T是一个左值引用类型时它不起作用.当然,我们可以部分专门ValueHolder使用直接初始化引用和std::move值,但这似乎std::forward是工作时的过度复杂.对于以下含义,这似乎也是一个合理的概念匹配std::forward:我们试图通常转发可能会或可能不会引用的内容,只有我们将它转​​发给函数的调用者,而不是我们调用的函数.我们自己.

这是一个合理的用途std::forward …

c++ templates move-semantics perfect-forwarding c++11

12
推荐指数
1
解决办法
2527
查看次数

我应该在移动ctors /赋值运算符中使用std :: move或std :: forward吗?

除非我错了,否则它们似乎都运行得很好 - 是否有一个最佳实践理由更喜欢一个而不是另一个?

例:

struct A
{
    A(){}
    A(const A&){ std::cout << "A(const A&)\n"; }
    A(A&&){ std::cout << "A(A&&)\n"; }
};

struct B
{
    B(){}
    B(const B& right) : x(right.x){ std::cout << "B(const B&)\n"; }
    B(B&& right) : x(std::forward<A>(right.x)){ std::cout << "B(B&&)\n"; }

    A x;
};

struct C
{
    C(){}
    C(const C& right) : x(right.x){ std::cout << "C(const C&)\n"; }
    C(C&& right) : x(std::move(right.x)){ std::cout << "C(C&&)\n"; }

    A x;
};

struct D
{
    D(){}
    D(const D& right) : x(right.x){ …
Run Code Online (Sandbox Code Playgroud)

c++ c++11

9
推荐指数
1
解决办法
3308
查看次数

为什么std :: forward在这种情况下无用

我注意到std::forward在这方面没有用处:

void consumeObject(std::unique_ptr<Object>&& robj) {
  myvector.emplace_back(std::forward<std::unique_ptr<Object>>(robj));
}
Run Code Online (Sandbox Code Playgroud)

这是为什么?我认为当rvalue引用绑定到一个函数参数时(即我可以通过名称引用它),它在该范围内变为左值,并且为了被传递,需要被转换为右值引用(如在完美转发中) ).

为什么它错了/没用?

c++

9
推荐指数
1
解决办法
791
查看次数

std :: move或std :: forward,参数为std :: unique_ptr <T> &&

我有一个名为PushC++ 11中编写的方法的以下模板类(剥离以仅包含相关部分):

template<class T, int Capacity>
class CircularStack
{
private:
    std::array<std::unique_ptr<T>, Capacity> _stack;

public:
   void Push(std::unique_ptr<T>&& value)
   {
      //some code omitted that updates an _index member variable

      _stack[_index] = std::move(value);
   }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:

我应该使用std::move还是std::forward在内Push

我不确定是否std::unique_ptr<T>&&有资格作为通用参考,因此应该使用forward而不是move.

我是C++的新手.

c++ c++11

7
推荐指数
1
解决办法
751
查看次数