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

aar*_*rkk 2 c++ stl vector

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

// Get access to the vertices and faces
auto vertices = t.GetVertices();
auto faces    = t.GetFaces();
Run Code Online (Sandbox Code Playgroud)

该功能的实现是这样的:

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

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

private:
  std::vector<glm::vec3>  vertices_;
  std::vector<glm::ivec3> faces_;
Run Code Online (Sandbox Code Playgroud)

无论出于何种原因,我都希望返回一个const引用几乎不会导致性能损失,但是这个操作似乎真的让程序陷入困境.我在这里错过了什么?这是否在发布模式下得到优化,但总是在调试模式下进行?

Fil*_*efp 8

为什么要复制内容?

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

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


我怎样才能防止这种情况发生?

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

auto const& vertices = t.GetVertices ();
auto const& faces    = t.GetFaces ();
Run Code Online (Sandbox Code Playgroud)

如何推断facesvertices推断?

具有表达式auto foo = init,foo将具有为以下模板函数的参数推导出的类型,称为deduce_type (init)其参数.

template<class T> void deduce_type (T);
Run Code Online (Sandbox Code Playgroud)

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

是否有一些解决方法,以便我总是得到确切的类型?

不,不是现在,但是在即将推出的C++标准(C++ 14)中,您将能够执行以下操作,结果将是您不正确地期望原始代码执行的操作:

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