C ++ noob:初始化时避免冗余对象拷贝的正确方法?

时间:2014-08-25 18:09:17

标签: c++ oop pointers scope initialization

我做了一个小例子:

#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的列表,PolyListPolygon:s的列表。Polygon:s通过实例化临时add()

PolyListPolygon

现在,这会泄漏内存,因为Polygon中的顶点永远不会被释放。但是,如果我添加一个析构函数:     Polygon :: ~Polygon(){delete [] vertices} 然后     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&lt;&gt;或另一种“罐装解决方案”;这不是我在这里所说的,虽然我确信如果上面的例子是我遇到的实际问题,这是一个很好的解决方案。上面的例子只是我能想到解释我的问题的最简单的例子。

2 个答案:

答案 0 :(得分:1)

您可以使用smart pointersSTL containers(主要是std::vector,如PaulMcKenzie所建议的那样)。

他们会帮助很多。

使用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

答案 1 :(得分:0)

您可以使用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;
}