我来自 Java,在那里填充容器不需要思考。我现在使用 C++ 的问题是,用在函数范围内声明的数据填充函数中的容器会导致错误,当我想访问它时数据不再存在。 我找不到解决这个问题的教程,所以我采用了 Java 方式,只让容器获得用“new”声明的指针。但是现在我被迫返回一个
std::list<Vertex<float> >
从一个函数开始,我认为这可能是学习如何填充和返回这样一个东西的好时机。这会不会
{
std::list<Vertex<float> > myList;
Vertex<float> v(0.0, 0.1, 0.2);
myList.push_back(v);
myList.push_back(Vertex<float>(1,0, 1.1, 1.2));
return myList;
}
作为示例函数体真的可以吗?如果是,为什么 v 仍然存在于范围之外?容器中的每次插入是否也意味着复制?
最佳答案
这会“很好”地工作,因为那里的每个操作都会创建一个拷贝。
myList.push_back(v);
创建了v
的拷贝,这样v
的可见性现在就无关紧要了。return myList;
将列表的拷贝返回给调用函数,因此 myList 的可见性现在无关紧要。调用函数应该复制此列表以将其保留在范围内,否则它将在调用此函数的行执行结束时被销毁。
之所以引用 fine 是因为拷贝通常很贵。在您的情况下,它们非常小,因此可能无关紧要,并且在许多情况下,它们可能会被优化掉,但仍然需要牢记这一点。
旧的 C++ 优化方式是通过引用传递列表并使用它来构造您的列表,而不是通过值返回。
void MakeMeAList(std::list<Vertex<float> >& aList){
....
}
std::list<Vertex<float> > aList;
MakeMeAList(aList);
正如@billz 所暗示的那样,Return Value Optimization即使没有这样做,也应该优化掉拷贝。
新 C++ (c++11) -
使用 emplace_back
来构造列表,只要不再使用输入变量,就会比复制更有效。 (感谢@Troy)
我的 C++11 很弱,我几乎可以肯定即使按值返回也是可以的,因为 Move 语义会优化它,但我只有 95% 的把握。
关于c++ - 在函数中填充容器避免段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14311637/