返回向量的第一个元素(重新)设置为 0

First element of returned vector is (re)set to 0

本文关键字:设置 重新 向量 第一个 元素 返回      更新时间:2023-10-16

我在软件中使用给定的库时遇到了这个问题。一个函数返回我想要使用的const std::vector&。但是,第一个值始终设置为零(或在我的原始代码中:所有坐标设置为 0.0 的 3D 矢量),尽管我事先存储的值不是。

类结构如下(示例代码如下):

  • ValueContainer :包含值的std::vector< double >和 getter values()
  • Object :包含一个ValueContainer和一个吸气valuesContainer()

在我的代码中,我使用以下方法检索值:

// First element always set to 0
const std::vector< double >& values = object.valuesContainer().values();

这导致了错误,即第一个元素设置为 0.0 。我可以通过复制值来规避问题:

// This works as expected
std::vector< double > values = object.valuesContainer().values();

仔细检查后,我注意到,valuesContainer()没有返回参考文献,而是返回ValueContainer的副本。发生的情况是(在我的理解中),我在valuesContainer()创建的临时对象上调用values(),从而获得对临时对象的引用。这当然不会很好地工作,我希望在我的向量中获得"垃圾"数据,或类似的东西。

但是:除了第一个值之外的所有值似乎都可以!现在,真正的问题是:为什么它会这样工作?如果它只是未定义的行为,为什么第一个值设置为 0 而其他值保持不变?我很乐意对这个问题有更多的了解。

下面是在 Linux 上使用 gcc 4.8.1 测试的示例代码:

#include <iostream>
#include <iomanip>
#include <vector>
class ValueContainer
{
    public:
        ValueContainer();
        inline const std::vector< double >& values() const;
    //private:
        std::vector< double > some_values_;
};
class Object
{
    public:
        ValueContainer valueContainerCopy() const
        {
            return values_;
        }
        const ValueContainer& valueContainerConstRef() const
        {
            return values_;
        }
    //private:
        ValueContainer values_;
};
ValueContainer::ValueContainer()
{
    // Just some test data
    some_values_.push_back(1.2);
    some_values_.push_back(3.4);
    some_values_.push_back(5.6);
    some_values_.push_back(7.8);
    some_values_.push_back(9.0);
}
const std::vector< double >& ValueContainer::values() const
{
    return some_values_;
}

int main( int argc, char** argv )
{
    Object obj;
    const std::vector< double >& values_CopyRef  = obj.valueContainerCopy().values();
    const std::vector< double >& values_RefRef   = obj.valueContainerConstRef().values();
    std::vector< double >        values_CopyCopy = obj.valueContainerCopy().values();
    std::cout << "Pointers: " << std::endl
              << " - Original: " << &obj.values_.some_values_ << std::endl
              << " - CopyRef:  " << &values_CopyRef << std::endl
              << " - RefRef:   " << &values_RefRef << std::endl
              << " - CopyCopy: " << &values_CopyCopy << std::endl;
    std::cout << "Data pointers: " << std::endl
              << " - Original: " << obj.values_.some_values_.data() << std::endl
              << " - CopyRef:  " << values_CopyRef.data() << std::endl
              << " - RefRef:   " << values_RefRef.data() << std::endl
              << " - CopyCopy: " << values_CopyCopy.data() << std::endl;
    std::cout << "Data:" << std::endl;
    for ( std::size_t i = 0; i < values_RefRef.size(); i++ )
    {
        std::cout << "i=" << i << ": " <<  std::fixed << std::setprecision(1)
                  << "CopyRef: "  << values_CopyRef[ i ] << ", "
                  << "RefRef: "   << values_RefRef[ i ] << ", " 
                  << "CopyCopy: " << values_CopyCopy[ i ] 
                  << std::endl;
    }
    return 0;
}

此示例的(重要)输出如下所示,您可以在其中看到,对临时对象的引用的第一个值设置为 0,其他值似乎没问题:

i=0: CopyRef: 0.0, RefRef: 1.2, CopyCopy: 1.2
i=1: CopyRef: 3.4, RefRef: 3.4, CopyCopy: 3.4
i=2: CopyRef: 5.6, RefRef: 5.6, CopyCopy: 5.6
i=3: CopyRef: 7.8, RefRef: 7.8, CopyCopy: 7.8
i=4: CopyRef: 9.0, RefRef: 9.0, CopyCopy: 9.0
const std::vector< double >& values_CopyRef  = obj.valueContainerCopy().values();

这是存储对临时函数的引用,因为valueContainerCopy函数被声明为

ValueContainer valueContainerCopy() const
{
    return values_;
}

这会将向量values_复制到返回的临时向量中。 然后,您将对该临时数据的引用存储,从而导致未定义的行为。

如果要将其存储为引用,则需要返回一个引用,这就是您在valueContainerConstRef函数中所做的。