当我尝试返回const引用时,为什么会出现矢量副本?

时间:2014-06-06 19:27:21

标签: c++ vector stl

我正在测量我在调试模式中运行的小演示的性能。这些操作似乎需要很长时间,并且正在进行复制操作(或者在调试时出现):

// 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引用几乎不会导致性能损失,但是这个操作似乎真的让程序陷入困境。我在这里错过了什么?这是否在发布模式下得到优化,但总是在调试模式下发生?

2 个答案:

答案 0 :(得分:8)

为什么要复制内容?

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

如果数据成员vertices发生变化,编译器会假定您不希望vertices_的内容发生变化;因为那是你宣布变量的方式。


如何防止这种情况发生?

如果您想将其声明为引用,则必须明确说明:

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

如何推断facesvertices的类型?

使用表达式auto foo = initfoo将具有针对以下模板函数的参数推导出的类型,称为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&`

答案 1 :(得分:0)

您必须记住,使用/向另一个对象分配或初始化对象,将以某种方式结束该对象的副本。虽然您提供的函数会返回常量引用,但它们会被分配(或复制)到新的实例化中。

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