推向向量向量时的错误
Error when pushing to vector of vectors
我有一个指向向量向量的指针,
vector< vector<Edge*> >* adj;
和initilized,
adj = new vector< vector<Edge*> >(v, vector<Edge*>());
当我推回这个向量的向量时,
Edge* e = new Edge(v, w);
adj[u].push_back(e);
我有一个错误,
prog.cpp:27:20: error: no matching function for call to ‘std::vector<std::vector<Edge*> >::push_back(Edge*&)’
adj[u].push_back(e);
^
我不明白这是怎么回事,我正确地使用了吗?第一:
Edge* e = new Edge(v, w);
(*adj)[u].push_back(e);
// ^
但是,再说一次,您为什么要 new
in and tockify and operify othert?您可以简单地做
// Create v amounts of vector<Edge>s
vector< vector<Edge> > adj(v, vector<Edge>());
Edge e(v, w);
adj[u].push_back(e); // assuming u is a valid index
它更容易阅读,更少的错误容易出现(您不必手动delete
所有内容),而且我确定比旧版本更具性能。
更新:哦,e
不需要被删除。
您需要一个二维阵列的事实使您误入歧途:对向量内的向量没有什么特别的,它只是具有二维的方便副作用。
所以让我们首先看一下std::vector<int>
。
#include <vector>
#include <iostream>
class Point {
int m_x, m_y;
public:
Point() : m_x(0), m_y(0) {}
Point(int x, int y) : m_x(x), m_y(y) {}
int X() const { return m_x; }
int Y() const { return m_y; }
};
class Edge {
Point m_start, m_end;
public:
Edge() : m_start(), m_end() {}
Edge(const Point& start, const Point& end)
: m_start(start)
, m_end(end)
{}
Edge(int startX, int startY, int endX, int endY)
: m_start(startX, startY)
, m_end(endX, endY)
{}
const Point& Start() const { return m_start; }
const Point& End() const { return m_end; }
};
void dumpEdges(const char* label, const std::vector<Edge>& edges)
{
std::cout << label << ":"
<< " edges.capacity = " << edges.capacity()
<< " edges.size = " << edges.size()
<< 'n';
for (size_t i = 0, end = edges.size(); i < end; ++i) {
std::cout << " edges["<<i<<"] = { "
<< edges[i].Start().X() << ", "
<< edges[i].Start().Y() << ", "
<< edges[i].End().X() << ", "
<< edges[i].End().Y() << " }n"
;
}
std::cout << 'n';
}
int main()
{
std::vector<Edge> edges;
// this has created an empty, dimensionless vector on the stack.
// when we push something to it, it will internally allocate memory
// to store an Edge for us.
dumpEdges("start", edges);
edges.push_back(Edge(0, 0, 0, 0));
dumpEdges("added 0,0,5,0", edges);
// when we now push another Point onto this vector, it may find
// it has used all the memory it allocated forcing it to allocate
// more memory. When this happens, our previous "Point" object
// will end up at a new address. We can avoid issues with this by
// using index values rather than absolute addresses.
edges.push_back(Edge(5, 0, 5, 5));
dumpEdges("added 5,0,5,5", edges);
// to save the program allocating memory every time we add a new
// edge, we can predict how many we're going to need.
edges.reserve(5);
dumpEdges("reserve'd to 5", edges);
// watch where the next push_back goes.
edges.push_back(Edge(5, 5, 0, 5));
dumpEdges("added 5,5,0,5", edges);
// but when you use resize, you actually add empty elements:
edges.resize(6);
dumpEdges("resize'd to 6", edges);
// watch where the next one goes.
edges.push_back(Edge(0, 5, -5, 5));
dumpEdges("added 0,5,-5,5", edges);
return 0;
}
这是来自IDEONE.com(http://ideone.com/wp5rxr)的输出:
开始:edges.capacity = 0 edges.size = 0
添加0,0,5,0:edges.capacity = 1 edge.size = 1 边缘[0] = {0,0,0,0,0}
添加了5,0,5,5:edge.capacity = 2 edge.size = 2 边缘[0] = {0、0、0、0} 边缘[1] = {5,0,5,5}
储备至5:edge.capacity = 5 edge.size = 2 边缘[0] = {0、0、0、0} 边缘[1] = {5,0,5,5}
添加了5,5,0,5:edges.capacity = 5 edge.size = 3 边缘[0] = {0、0、0、0} 边缘[1] = {5,0,5,5} 边缘[2] = {5,5,0,5}
调整到6:edges.capacity = 6 edge.size = 6 边缘[0] = {0、0、0、0} 边缘[1] = {5,0,5,5} 边缘[2] = {5,5,0,5} 边缘[3] = {0,0,0,0} 边缘[4] = {0、0、0、0} 边缘[5] = {0,0,0,0,0}
添加0,5,-5,5:edges.capacity = 12 edges.size = 7 边缘[0] = {0、0、0、0} 边缘[1] = {5,0,5,5} 边缘[2] = {5,5,0,5} 边缘[3] = {0,0,0,0} 边缘[4] = {0、0、0、0} 边缘[5] = {0,0,0,0} 边缘[6] = {0,5,-5,5}
在这一点上,您应该拥有使用std :: vector的能力,但是对于特定用例,您需要记住std :: vector是通用的。您 can 将另一个向量包裹在其中, std::vector<std::vector<Edge>>
。但这只是两个独立工作的向量。
void fn()
{
std::vector<std::vector<Edge>> adj;
adj
这是一个简单的std::vector
,其中adj[n]
解决std::vector<Edge>
的实例。这两个向量并不真正了解彼此。adj[x][y]
工作的事实是方便的魔术,它不是向量的特殊功能。它将适用于任何 std::vector<
对象 - implements-operator [] >
。
编写adj[12][7]
时,实际发生的事情是我们采用顶级对象,adj
(键入std :: vector> , and calling it's member function
操作员. This returns a reference to the 12th element of the top vector, type
std :: vector , on which we then invoke
运算符。>
adj . operator[](12) . operator[](7);
或
auto& object = adj;
auto& outerVectorElement = object.opterator[](12);
outerVectorElement.operator[](7);
此代码:
std::vector<std::vector<Edge>> adj(5);
创建一个std::vector<T>
,并使用A size 的5。
std::vector<T> adj;
adj.resize(5);
现在,在上述情况下,T恰好是std::vector<Edge>
。因此,它创建了5个向量的向量。
std::vector<std::vector<Edge>> adj(5, std::vector<Edge>());
这做类似但更昂贵的事情,实际上更像是这样:
std::vector<T> adj;
adj.reserve(5);
for (size_t i = 0; i < 5; ++i)
adj.push_back(std::vector<Edge>());
因为那是"具有初始值的填充"的语法。它可能导致创建暂时的Edge
对象。如果您想要的只是默认初始化,并且确定您需要固定的初始大小,只需使用
std::vector<T> adj(N);
更多代码:
std::vector<std::vector<Edge>> adj(initialSize);
std::vector<Edge>& firstAdjVec = adj[0];
firstAdjVec.push_back(Edge(1,2,3,4));
此时,adj是5个向量的向量。其中的第一个现在包含一个单个边缘。我们可以将其称为:
firstAdjVec[0];
adj[0][0];
(adj[0])[0];
auto& vec = adj[0]; vec[0];
这看起来像一个二维阵列,但事实并非如此。它是一个一维向量的数组,它们本身都有自己的向量数据,但它们是独立的。
如果您在C/C 中执行此操作:
Edge adj[10][12];
这将分配一个大的,连续的内存块,10 x 12。存储自己的元素。
这允许可变维度:
std::vector<std::vector<int>> grid;
grid.resize(10); // first dimension is now 0-10, all rows are 0 depth.
grid[0].push_back(1);
grid[2].push_back(2);
grid[2].push_back(3);
grid[0][0]; // returns 1;
grid[0][1]; // invalid, exceeds dimensions of std::vector& (grid[0]);
grid[1][0]; // invalid, std::vector& (grid[1]) is empty.
grid[2][1]; // valid
grid[3][0]; // invalid - empty.
最后是跟踪特定边缘的问题。您的代码使用指针来边缘*对象。除非您更熟悉指针,否则这是导致内存泄漏。将指针放入向量确实不是使其成为指针的所有者。如果您不希望应用程序用完存储器,则负责将内存返回系统。您需要为此使用delete
。
两个替代方案:一个,不要。只需删除指针并让您的向量管理内存即可。
std::vector<Edge>
瞧。不利的一面是,如果您想将这些边缘保留到其他地方,
void fn(Edge*);
当向量生长时,您将遇到问题:
#include <iostream>
#include <vector>
struct Foo {
int m_i;
char m_pad[1024]; // to make the object big.
Foo(int i) : m_i(i) { m_name[0] = ' '; }
};
int main()
{
std::vector<Foo> foos;
// grow the storage to support 4 Foos.
foos.reserve(4);
// emplace_back is like push_back but it passes
// it's arguments directly to the constructor of
// the new object, initializing it in-place, avoiding
// a copy. so foo.emplace_back(1) will initialize
// the new Foo by calling it's constructor with the value '1'.
foo.emplace_back(1);
std::cout << "First foo's address is " << (void)&foos[0] << 'n';
// push 3 more.
foo.emplace_back(2);
foo.emplace_back(3);
foo.emplace_back(4);
std::cout << "First foo's address is " << (void)&foos[0] << 'n';
// but now add lots more to force the storage to grow.
foo.resize(64);
std::cout << "First foo's address is now " << (void)&foos[0] << 'n';
return 0;
}
要避免这种情况,只需使用索引而不是指针:
#include <vector>
#include <iostream>
struct Edge {
Edge(int i=0) : m_i(i) {} // kill two birds with one constructor.
int m_i;
};
typedef std::vector<std::vector<Edge>> EdgeGrid;
void pointerVersion(Edge* edge)
{
std::cout << "pointing to " << (void*)edge << " -> " << edge->m_i << 'n';
}
void indexVersion(const EdgeGrid& adj, size_t x, size_y)
{
std::cout << "adj["<<x<<"]["<<y<<"] = " << adj[x][y] << 'n';
}
int main()
{
std::vector<std::vector<Edge>>> adj;
adj.resize(4);
adj[1].push_back(1);
adj[1].push_back(2);
adj[1].push_back(3);
pointerVersion(&adj[1][2]);
indexVersion(adj, 1, 2);
return 0;
}
当然,在这种情况下,您不必总是将adj
推到班级本身,那么您只需要告诉您要引用哪个x和y。
class EdgeContainer
{
std::vector< std::vector< Edge > > m_adj;
public:
EdgeContainer() : m_adj(10) {}
// ...
};
更好的是,您可以通过给它来使其看起来像二维矢量
const std::vector<Edge>& operator[](size_t topIndex) const
{
return m_adj[topIndex];
}
现在您可以做:
EdgeContainer adj;
// .. code to populate adj here
std::cout << "adj[3][1] = " << adj[3][1] << 'n';
记住,这实际上是在执行adj.operator[](3)
,该CC_26返回对内部向量的引用,然后我们在该vector上调用方法operator[](1)
。
- C++中函数的向量返回类型引发错误
- 尝试将unique_ptrs推送到向量时使用纯虚拟函数错误
- 在c++中键入向量中的所有值后,得到分段错误(核心转储)
- 如何使用C++初始化向量;脚本化值不是数组、指针或矢量错误
- 对象指针 c++ 的全局向量错误
- C++:自定义数据类型向量错误的队列
- getCompatibleComponent返回向量错误
- FlatBuffers:未支撑的工会向量错误将JSON文件转换为二进制文件
- 尝试调用 at() 时 c++ 中的向量错误
- 结果向量错误
- 尝试用函数填充线程向量 - 错误
- C++ 布尔向量错误:赋值时"iterator not dereferencable"
- CUDA 推力:类的:d向量 |错误
- C++多结构向量错误
- c++正则化向量;错误:无法绑定
- c++向量错误
- 向量错误抛掷分配经验甚至不访问任何元素
- std::函数的向量错误
- STL向量错误:未知类型名称
- 向量错误分配错误 C++