C++ std::find() 寻址返回向量的类函数时的意外行为

Posted

技术标签:

【中文标题】C++ std::find() 寻址返回向量的类函数时的意外行为【英文标题】:C++ std::find() unexpected behavior when addressing a Class function returning a vector 【发布时间】:2019-07-31 22:37:26 【问题描述】:

我是一个理论问题。我有一个类Patient,其中有一个函数返回类本身的向量Patient.getVars()

class Patient 
  #... rest of class ...
  std::vector<std::string> vVar;
  public :
    void addVar( std::string var )
    
      vVar.push_back(var);
    
    std::vector<std::string> getVars()
    
       return vVar;
    ;
  #... rest of class ...

我注意到,如果我使用 std::find() 检查向量 vVar 调用类函数的元素:

if ( std::find ( vPatientClass[ posPz ].getVars().begin(), vPatientClass[ posPz ].getVars().end(), var_name ) == vPatientClass[ posPz ].getVars().end() ) 
# .... rest of code ....

当它实际上是不存在时,它告诉我它是 PRESENT,反之亦然。

否则,如果我复制向量并在其上查找:

std::vector<std::string> vPzVars = vPatientClass[ posPz ].getVars();
if ( std::find ( vPzVars.begin(), vPzVars.end(), var_name ) == vPzVars.end() ) 
# .... rest of code ....

它的行为符合预期!这对我来说很重要……有什么线索吗?

PS:我通过[ posPz ] 的位置来寻址Patient 对象,因为vPatientClassPatient 类对象的向量。

提前感谢您的任何建议!

【问题讨论】:

getVars() 每次调用时都会返回一个副本。这不仅可能会很慢,而且还会导致您看到的问题。在std::find ( vPatientClass[ posPz ].getVars().begin(), vPatientClass[ posPz ].getVars().end(), var_name ) 中,您将迭代器传递给两个不同的 向量(同一向量的两个副本),这是不允许的。返回参考:const std::vector&lt;std::string&gt; &amp;getVars() const 所以我可以将矢量公开并直接访问它...对吗? 或者引用返回 你可以保留副本,但要事先有auto patients = vPatientClass[posPz].getVars(); @HolyBlackCat 听起来像是一个答案! 【参考方案1】:

您的getVars 成员正在返回内部向量的副本

std::vector<std::string> getVars()

   return vVar;
;

因此,在您有问题的std::find 调用中,您调用Patient::getVars() 3 次并获得3 个不同的向量副本。虽然值相同,但您从 begin()end() 获得的迭代器彼此不兼容。你可以通过引用返回你的向量:

const std::vector<std::string>& getVars() const

   return vVar;
;

【讨论】:

以上是关于C++ std::find() 寻址返回向量的类函数时的意外行为的主要内容,如果未能解决你的问题,请参考以下文章

如何仅通过向量对的第一个元素或自定义向量三元组使用 std::find?

std::find 条件语句未按预期工作

带有自定义比较器的 C++ std::find

C++,成员函数返回对包含指向 const 对象的指针的向量的 const 引用

C++ CppCheck算法建议(std::find_if代替原始循环)相关性

将“push_back”用于带有“get”函数C++的向量