在我的软件中使用给定库时遇到了这个问题。一个函数返回一个const std::vector&
我想使用的。但是,第一个值始终设置为零(或在我的原始代码中:所有坐标设置为 0.0 的 3D 向量),尽管我事先存储在其中的值不是。
类结构如下(示例代码如下):
ValueContainer
: 包含一个std::vector< double >
值和 gettervalues()
。Object
: 包含一个ValueContainer
, 和一个 gettervaluesContainer()
。
在我的代码中,我检索了以下值:
// 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
. 发生的事情是(在我的理解中),我调用values()
了一个由创建的临时对象valuesContainer()
,从而获得了对临时对象的引用。这当然不能很好地工作,我希望在我的向量中得到“垃圾”数据,或者类似的东西。
但是:除了第一个值之外的所有值似乎都可以!现在,真正的问题是:为什么它会这样工作?如果只是未定义的行为,为什么第一个值设置为 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