【问题标题】:Do I Need to use ref With make_pair to Return a Reference?我需要使用 ref 和 make_pair 来返回参考吗?
【发布时间】:2019-09-09 19:22:41
【问题描述】:

给定一个像这样的对象:

struct Foo {
    string _mem;
    pair<bool, const string&> Func() { return make_pair(true, _mem); }
};

我是否真的返回了对_mem 的引用?我的理解是 make_pair 会转发我的类型,允许我使用返回来捕获它作为对对象 _mem 的引用。

这种行为似乎与我在 gcc 8 中看到的一致:http://ideone.com/adz17e 但是当我尝试在 上运行它时,它会出现段错误。如果我更改为返回 make_pair(true, ref(_mem)) 它可以工作,但我认为我不需要这样做。这些行为哪一种是正确的?

【问题讨论】:

    标签: c++14 visual-studio-2017 c++ reference visual-studio-2017 c++14 std-pair


    【解决方案1】:

    我是否真的返回了对_mem 的引用?

    不,你不是。 make_pair(true, _mem) 是 std::pair&lt;bool, std::string&gt;,是您的成员的副本。然后它在返回类型中转换为std::pair&lt;bool, std::string const&amp;&gt;,这意味着您正在返回对立即销毁的临时对象的引用。无条件悬空。

    回想一下,C++ 是一种值语义语言。默认情况下没有任何参考,您必须明确说明这一点。

    您有两种方法可以做到这一点。您可以标记您想要参考:

    return std::make_pair(true, std::ref(_mem));
    

    make_pair 将解开std::reference_wrappers,所以这个表达式是std::pair&lt;bool, std::string&amp;&gt;。

    或者,您可以明确表示:

    return std::pair<bool, std::string const&>(true, _mem);
    

    你可以写成更短的:

    return {true, _mem};
    

    【讨论】:

      【解决方案2】:

      这是未定义的行为。

      由于c++11 make_pair 被定义为:

      template< class T1, class T2 >
      std::pair<V1,V2> make_pair( T1&& t, T2&& u );
      

      在你的情况下,_mem 是左值,所以T2 被推导出为string&amp;,但结果对的V2 是从std::decay(string&amp;) 推导出来的。 std::decay 总是丢弃引用。返回的对在second 成员中有悬空引用。

      【讨论】:

      • 我编辑了问题以添加我的解决方法,但我不确定您的回答是否有意义。我现在回来了:make_pair(true, ref(_mem)),这似乎有效。这不会也衰减为仅按类型返回吗?
      • @JonathanMee decay reference_wrapper&lt;string&gt; 给你string&amp;。你不需要使用ref,只需在模板参数列表中明确输入类型:pair&lt;bool,const string&amp;&gt;(true,_mem)。这个make_tuple(true,_mem) 与pair&lt;bool,string&gt;(true,_mem) 相同,所以_mem 被复制到本地范围内,这就是你得到悬空引用的原因。
      猜你喜欢
      • 2010-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-27
      相关资源
      最近更新 更多