当我尝试返回const引用时,为什么会发生矢量复制?

Why is a vector copy occurring when I try to return a const reference?

本文关键字:复制 为什么 返回 const 引用      更新时间:2023-10-16

我正在测量我在调试模式下运行的一个小演示的性能。这些操作似乎花费了很长时间,并且正在引发复制操作(或者在调试时看起来是这样):

// Get access to the vertices and faces
auto vertices = t.GetVertices();
auto faces    = t.GetFaces();

该函数的实现如下:

std::vector<glm::vec3>  const& GetVertices() const { return vertices_; }
std::vector<glm::ivec3> const& GetFaces()    const { return faces_;    }

在包含以下私有成员的类中:

private:
  std::vector<glm::vec3>  vertices_;
  std::vector<glm::ivec3> faces_;
无论出于什么原因,我希望返回一个const引用几乎不会带来任何性能损失,但是这个操作似乎确实使程序陷入了困境。我遗漏了什么?这是否在发布模式下得到了优化,但总是在调试模式下发生?

为什么要复制内容?

verticesfaces的类型分别为std::vector<glm::vec3>std::vector<glm::ivec3>。初始化它们时,编译器需要从返回的引用中复制内容。

编译器假定当数据成员vertices_发生变化时,不希望vertices的内容发生变化;因为这是你声明变量的方式。


我怎样才能避免这种情况的发生?

如果你想将它们声明为引用,你必须明确地这样说:

auto const& vertices = t.GetVertices ();
auto const& faces    = t.GetFaces ();

如何推断出facesvertices的类型?

有了表达式auto foo = init, foo将具有为下面模板函数的实参(称为deduce_type (init))推导出来的类型作为其形参。

template<class T> void deduce_type (T);

<一口>

                               // auto vertices = t.getVertices ();
deduce_type (t.getVertices ()) // imaginary call, T = std::vector<glm::vec3>

是否有一些变通办法,使我总是得到确切的类型?

不,目前还没有,但在即将到来的 c++ 标准中( c++ 14),你将能够做以下事情,结果将是你不准确地期望你的原始代码做的:

decltype(auto) vertices = t.GetVertices ();
//              ^-- vertices is of type `std::vector<glm::vec3> const&`

必须记住,用/to另一个对象赋值或初始化一个对象,将(以某种方式)以该对象的副本结束。当你给出的函数返回常量引用时,它们被赋值(或复制)给新的实例化。

您可以通过使用指针来避免这种情况(这将在堆栈上为指针分配内存,但在我看来这是一个名义因素),或者您可以使用move构造函数。我不知道我移动构造函数是否会工作,在这种情况下,但我最初的想法是它不会(因为分配的值应该是const)。

相关文章: