【问题标题】:Retrieving vector using pass-by-reference doesn't propagate clearing the underlying vector?使用传递引用检索向量不会传播清除底层向量?
【发布时间】:2014-08-05 19:15:36
【问题描述】:

我有一个场景,我使用传递引用获取 MyClass 的向量,如下所示:

std::vector<shared_ptr<MyClass>>& x = myObj->getVector();

但是当我这样做时:

x.clear();

我期望 myObj 中的底层向量大小为零,因为我使用传递引用检索它。然而,这种情况并非如此。这是为什么呢?

编辑:

返回的向量是一个数据成员,而不是在getVector() 中创建的向量。

EDIT2:这是getVector()

std::vector<shared_ptr<MyClass>> myVec;

std::vector<shared_ptr<MyClass>> getVector(){
    return myVec;
}

【问题讨论】:

  • getVector 是否通过引用返回?如果没有,您的代码不应该编译。
  • @ghostofstandardspast 不,它只是返回对象但是......我被引导相信方法的返回类型不是决定 PbR/PbV 的,它是调用代码(我的部分已在上面发布)有“&”?另外,我正在返回一个类数据成员......
  • 如果按值返回,您的对象将被复制/移动/RVOd 出。如果您没有将引用放在x 上,则会将其复制/移动到x。实际上,您的代码无效,因为右值无法绑定到左值引用。
  • 如果它返回一个值 copy,而不是非常量引用,那么要么您使用的编译器允许非常量引用临时变量(又名 MSVC ),或者该代码应该呕吐。无论哪种方式,原始向量都没有被清除。 显示 getVector()的声明。如果不返回引用,则不会修改成员。
  • 发布getVector() 的代码会很有用,这样我们就可以仔细检查它不是在创建副本。 myObj 类的定义也会有所帮助

标签: c++ vector pass-by-reference


【解决方案1】:

它只是返回对象

那么您的编译器不应接受此代码,因为调用getVector 的右值结果无法绑定到左值引用x。 Microsot 的编译器因拥有允许这种行为的语言扩展而臭名昭著,而且这种扩展被许多人讨厌。

我被引导相信方法的返回类型不是决定PbR/PbV的,而是调用代码(我上面贴的部分)是否有“&”?

如果作为引用仅由调用者决定,这会做什么?

myObj->getVector().clear();

相反,函数需要通过引用返回,以便调用者接收对对象的引用(使上述示例正常工作)。

如果您决定存储函数的结果,则变量必须是引用,否则结果将被复制或移动到变量中(在返回值是引用的情况下复制)。调用者的变量也可以通过 RVO 直接构造,但同样,当返回值是引用时不能。

C++ 传递和返回按值,除非使用了引用。默认值为值语义,您可能认为这很糟糕,但当移动语义开始发挥作用时,最终效果会好很多。

【讨论】:

  • @πάνταῥεῖ,我有一种直觉,但 OP 确实在 cmets 中进行了详细说明。 “不,它只是返回对象”也许我的答案可以更好地格式化以包含相关基础。
  • '但是 OP 确实在 cmets 中进行了详细说明。' 这是不好的行为,OP 应该知道(或者在他们的日常谷物盒中找到他的代表:P)。
  • @user997112 '这是 MSVC...' 不!
【解决方案2】:

您可以使用多种方法解决此问题。

  1. 更改getVector()的返回类型以返回对成员数据的引用。

    std::vector<shared_ptr<MyClass>>& getVector(){
      return myVec;
    }
    

    然后,你可以使用

    myObj->getVector().clear();
    

    清除myObj-&gt;myVec的内容。

  2. 添加成员函数clearVector()并调用它。

    void clearVector(){
      myVec.clear();
    }
    

    然后,你可以使用

    myObj->clearVector();
    

【讨论】:

  • 我喜欢#2。没有 sudo 访问对象的向量。
  • @ghostofstandardspast 我喜欢“sudo 访问”这个词 :)
  • 我只是想到它,所以它可能已经完成了,但它非常适合,不是吗?
猜你喜欢
  • 2017-11-27
  • 2012-08-31
  • 2016-09-06
  • 1970-01-01
  • 2021-04-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多