【问题标题】:Dangers of storing rvalue references in templates在模板中存储右值引用的危险
【发布时间】:2018-03-14 21:29:11
【问题描述】:

考虑以下代码:

#include <functional>

template<class T>
class factory {
public:
    factory(T &&t) : t_(std::forward<T>(t)) {}

private:
    T &&t_;
};

template<class T>
factory<T> make_factory(T &&t) {
    return factory<T>(std::forward<T>(t));
}

int main(){
    int i = 3;
    auto bar = make_factory(i); //now it will store int &
    auto foo = make_factory(5); //now will store int &&
    return 0;
}

这当然是对代码的简化,但显示了我的一般想法——我正在考虑存储对右值的引用。据我所知,在第一种情况下,推导的类型将为int &amp;,因此工厂将在离开范围之前有效(由于引用折叠)。我的问题是

  1. foo 对象是否会导致未定义的行为?
  2. 如果不是,存储的右值引用的有效期是多久(我的意思是,它的范围是多少)?
  3. 我是否缺少任何注意事项?

编辑: 我认为这已经足够了,但我看到我必须澄清。我想实现这样的目标:

template<class T>
class factory {
public:
    factory(T &&t) : t_(std::forward<T>(t)) {}

    auto make() const & {
        return wrap(t_);
    }

    auto make() && {
       return wrap(/*what here, move(t_), forward<T>(t_) ?*/);
    }
private:
    T t_;//or maybe T&& here?
};

我不想复制该成员,除非我真的必须这样做。我想做一些类似通过factory 类转发的事情。

【问题讨论】:

  • 你为什么要考虑这样做?
  • 它的作用域就是那个表达式。
  • @NeilButterworth 我想传递大型物体(要精确的容器)。我正在尝试可能的解决方案,以尽量避免复制。
  • 使用指针怎么样?
  • @NeilButterworth 这是一个选项。正如我所说,我正在尝试。如果知道我在做什么,我不会这样称呼它;)

标签: c++ c++11 templates rvalue-reference


【解决方案1】:

一般这样做:

template<class T>
class factory {
public:
  factory(T &&t) : t_(std::forward<T>(t)) {}

private:
  T t_; // could be a lvalue ref
};

它只是工作。真的。是的,这种情况也是如此。

右值不应超过其封闭语句;所以你的制造工厂不应该返回一个包含右值引用的结构。

【讨论】:

  • 我可以通过这样的对象完美转发吗?
  • 对于 r/lvalue,这种方法将具有本质上不同的行为。恐怕以后容易造成隐藏的bug。
  • @lili 它的行为类似于auto&amp;&amp; 引用生命周期延长(或不是)。您也可以使用std::decay_t&lt;T&gt; t_; 来表示auto 类似的行为。
  • @Yakk:这里有个怪癖,它实例化了factory&lt;int&amp;&gt;factory&lt;int&amp;&amp;&gt;,而不是预期的factory&lt;int&gt;。这值得明确指出。
  • @mooing 是的,将衰减放入 make,然后在工厂 ctor 中完美转发,可能是一个更好的计划。
猜你喜欢
  • 1970-01-01
  • 2018-06-02
  • 2023-04-07
  • 2011-10-24
  • 1970-01-01
  • 1970-01-01
  • 2011-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多