我做了一个最小的例子:
#include <iostream>
#include <conio.h>
using namespace std;
// skipped getters and setters and bounds checking for brevity
struct Vertex {
int x,y;
Vertex() {
}
Vertex(int x, int y) {
this->x = x;
this->y = y;
}
};
struct Polygon {
Vertex *vertexlist;
Polygon() {
}
Polygon(Vertex *v) {
vertexlist = new Vertex[4]; //hard coded 4 vertices for example brevity
for(int i=0;i<4;i++) {
vertexlist[i] = v[i];
}
}
Vertex& getVertex(int index) const {
return this->vertexlist[index];
}
};
struct PolyList {
Polygon *polylist;
int lastpoly;
PolyList() {
polylist = new Polygon[10]; //hard coded 10 for example brevity
lastpoly = 0;
}
void add(const Polygon& p) {
polylist[lastpoly++] = p;
}
};
ostream& operator<<(ostream& o, Vertex& v) {
return o << "(" << v.x << ", " << v.y << ")";
}
ostream& operator<<(ostream& o, const Polygon& p) {
for(int i=0;i<4;i++) {
o << p.getVertex(i) << ", ";
}
return o;
}
ostream& operator<<(ostream& o, PolyList& pl) {
for(int i=0;i<pl.lastpoly;i++) {
o << pl.polylist[i] << endl;
}
return o;
}
int someFunc() {
Vertex *vl = new Vertex[4];
PolyList pl;
vl[0] = Vertex(1,2);
vl[1] = Vertex(3,4);
vl[2] = Vertex(5,6);
vl[3] = Vertex(7,8);
pl.add(Polygon(vl)); // this Polygon goes out of scope after this line
cout << pl << endl;
}
int main() {
someFunc();
}
(所以tl;dr, Polygon
是4x Vertex
的列表,PolyList
是Polygon
:s的列表。Polygon
:s通过实例化临时Polygon
,将add()
转换为PolyList
现在,这会泄漏内存,因为Polygon
中的顶点永远不会被释放。但是,如果我添加析构函数:Polygon::~Polygon(){删除[]顶点}然后cout & lt; & lt;pl & lt; & lt;endl;将不起作用,因为Polygon
已经超出了作用域,析构函数释放了顶点。
PolyList
析构函数调用Polygon->free()
函数。或者,我可以让Polygon::Polygon(Vertex *v)
深度复制v中的所有顶点,然后PolyList::PolyList(Polygon &p)
可以深度复制p。
我也可以做一个PolyList::createPolygon(int x1, int y1, int x2, int y2...)
,但这是在面对OO。
c++中处理这种情况的正确方法是什么?不要介意我的实际示例,在这个示例中内存泄漏不会成为问题,我说的是原则上的问题。如果我创建一个分层对象树,我想复制指针,而不是深度复制对象。
编辑:我正试图深入学习c++,所以这不是关于使用vector<>或另一个"罐装解决方案";这不是我在这里所追求的,尽管我确信如果上面的例子是我遇到的一个实际问题,这是一个很好的解决方案。上面的例子只是我能想到的最简短的例子来解释我的问题。
您可以使用智能指针和STL容器(主要是PaulMcKenzie建议的std::vector
)。
他们会帮很多忙的。
使用std::vector
的示例#include <iostream>
#include <conio.h>
#include <vector>
using namespace std;
// skipped getters and setters and bounds checking for brevity
struct Vertex {
int x, y;
Vertex() {
}
Vertex(int x, int y) {
this->x = x;
this->y = y;
}
};
typedef vector<Vertex> vertex_list_t;
struct Polygon {
vertex_list_t vertexlist;
Polygon() {
}
Polygon(vertex_list_t v) {
//hard coded 4 vertices for example brevity
for (int i = 0; i<4; i++) {
vertexlist.push_back(Vertex(i, i));
}
}
Vertex getVertex(int index) const {
return vertexlist[index];
}
};
typedef vector<Polygon> polygon_list_t;
ostream& operator<<(ostream& o, Vertex& v) {
return o << "(" << v.x << ", " << v.y << ")";
}
ostream& operator<<(ostream& o, const Polygon& p) {
for (auto v: p.vertexlist) {
o << v << ", ";
}
return o;
}
ostream& operator<<(ostream& o, polygon_list_t& pl) {
for (auto &p : pl) {
o << p << endl;
}
return o;
}
int someFunc() {
vertex_list_t vl = {
Vertex(1, 2),
Vertex(3, 4),
Vertex(5, 6),
Vertex(7, 8)
};
polygon_list_t pl;
pl.push_back(Polygon(vl)); // this Polygon goes out of scope after this line
cout << pl << endl;
return 0;
}
int main() {
someFunc();
}
什么是真正的交易?
pl.add(Polygon(vl)); // this Polygon goes out of scope after this line
你传递多边形作为临时的,
$12.2/3- "临时对象在(词法上)包含其创建点的完整表达式(1.9)求值的最后一步被销毁。即使该求值以抛出异常结束,也是如此。"
修改为:
Polygon p1(vl);
pl.add(p1); // this Polygon NOT goes out of scope after this line
您可以使用shared_ptrs作为解决方案。例如
#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include <memory>
#include <list>
#include <vector>
using namespace std;
struct Vertex
{
int x,y;
Vertex() : x(0), y(0)
{
}
Vertex(int _x, int _y)
{
x = _x;
y = _y;
}
};
struct Polygon
{
vector<Vertex> vertexes;
Polygon()
{
}
Polygon(Vertex *v)
{
const int ELEMS_COUNT = 4;
vertexes.reserve(ELEMS_COUNT);
vertexes.insert(vertexes.end(), v, v + ELEMS_COUNT);
}
Vertex getVertex(int index) const
{
return vertexes[index];
}
};
typedef shared_ptr<Polygon> PolygonPtr;
struct PolyList
{
std::list<PolygonPtr> polylist;
void add(PolygonPtr p)
{
polylist.push_back(p);
}
};
ostream& operator<<(ostream& o, const Vertex& v) {
return o << "(" << v.x << ", " << v.y << ")";
}
ostream& operator<<(ostream& o, const Polygon& p) {
for (auto& p : p.vertexes)
{
o << p << ", ";
}
return o;
}
ostream& operator<<(ostream& o, PolyList& pl) {
for(auto& p : pl.polylist)
{
o << *p << endl;
}
return o;
}
int someFunc() {
Vertex vl[] = {Vertex(1, 2), Vertex(3, 4), Vertex(5, 6), Vertex(7, 8)};
PolyList pl;
pl.add(PolygonPtr(new Polygon(vl)));
cout << pl << endl;
return 0;
}
int main()
{
someFunc();
return 0;
}