如何通过引用推送向量?
Posted
技术标签:
【中文标题】如何通过引用推送向量?【英文标题】:How do I push vectors by reference? 【发布时间】:2018-11-09 21:59:15 【问题描述】:下面的代码不起作用,因为我将向量 a 和 b 推回向量向量,然后更改向量 a 和 b。我想改变向量 a 和 b 以便向量向量遭受相同的修改。我该怎么做?
#include <iostream>
#include <vector>
int main()
std::vector<std::vector<int>>vector;
std::vector<int>a;
std::vector<int>b;
vector.push_back(a);
vector.push_back(b);
for (int i = 1; i <= 10; i++)
a.push_back(i);
for (int i = 11; i <= 20; i++)
b.push_back(i);
std::cout << vector[1][0];
std::cin.get();
【问题讨论】:
直接使用向量 - 例如vector[0].push_back(i)
在第一个循环中,而不是 a.push_back(i)
。
【参考方案1】:
您可以使用std::reference_wrapper
(C++11 起)。
std::reference_wrapper
是一个类模板,它将引用包装在可复制、可分配的对象中。它经常被用作在标准容器(如std::vector
)中存储引用的机制,这些容器通常不能保存引用。
例如
std::vector<std::reference_wrapper<std::vector<int>>> v;
std::vector<int> a;
std::vector<int> b;
v.push_back(a);
v.push_back(b);
for (int i = 1; i <= 10; i++)
a.push_back(i);
for (int i = 11; i <= 20; i++)
b.push_back(i);
std::cout << v[1].get()[0]; //11
LIVE
请注意,如果vector
的寿命比a
和b
更长,那么当a
和b
被销毁时,存储在vector
中的引用会变得悬空。
【讨论】:
这里的一个问题是v
在超出范围后包含对a
和b
的引用。【参考方案2】:
创建v
(vector
不是一个好名字,因为它与库共享并使代码混乱)成为vector
指针的vector
(因为a vector of references is not possible):
std::vector<std::vector<int> *> v; //declare as vec of vec pointers
...
v.push_back(&a); //push_back addresses of a and b
v.push_back(&b);
...
std::cout << v.at(1)->at(0) //dereference and call at on the inner vec
请注意,如果 a
或 b
在 v
之前超出范围,这可能会很危险,因为这会给您留下悬空指针、一堆未定义的行为和一个谋杀耗时的错误。
【讨论】:
如果向量(或它的副本)超过a
或b
,这是很危险的,因为它将包含悬空引用。【参考方案3】:
基本问题是push_back
将其参数复制到向量的末尾。要修改向量中的对象,您需要获取对它的引用。一种方法:
std::vector< std::vector<int> > my_vector;
my_vector.reserve(2); // Going over the allocation invalidates references
my_vector.push_back( std::vector<int>() );
std::vector<int> & a = my_vector.back();
my_vector.push_back( std::vector<int>() );
std::vector<int> & b = my_vector.back();
(我更改了变量的名称,因为使用“vector”作为变量名容易导致混淆。)
如果可以使用 C++17,有一种方法可以使用 emplace_back
减少代码行数。
【讨论】:
emplace_back
也存在于 C++11 和 C++14 中。
@Matt true,但是在C++17之前,它的返回类型是void
。
请小心,因为如果第二个push_back
增加了向量的容量,则从之前的back()
获得的引用将失效。
@JaMiT 非常正确,我没有看到你要去哪里,但现在很清楚了。
@RemyLebeau 好点。我添加了预订以避免这种情况。而且我承认可能有更好的方法来做事;在没有大局的情况下选择一个是很难的。【参考方案4】:
如果你提前知道向量的数量,你可以这样做:
std::vector<std::vector<int>> v(2);
std::vector<int> &a = v[0];
std::vector<int> &b = v[1];
...
【讨论】:
以上是关于如何通过引用推送向量?的主要内容,如果未能解决你的问题,请参考以下文章