Reference Counting in C ++

I am implementing a C ++ math library. The library will be compiled into a DLL, so those who use it will only need header files, class definitions.

Users of my classes will be people who are not familiar with the language. However, there are some objects that can be referenced in several parts of their programs. Since I do not expect them to be involved in memory management, I would like to do it myself. So I need to do reference counting (garbage collection is not an option).

I want to make this reference count as transparent as possible, for example ...

// Define a Bézier curve
CVecList pts;
pts.Add(Vector(0,0,0));
pts.Add(Vector(0,0,100));
pts.Add(Vector(0,100,0));
pts.Add(Vector(0,100,100));
CCurve* c1 = new CBezier(pts);

// Define a 3rd order B-Spline curve
pts.Clear();
pts.Add(Vector(0,0,0));
pts.Add(Vector(0,200,100));
pts.Add(Vector(0,200,200));
pts.Add(Vector(0,-200,100));
pts.Add(Vector(0,-200,200));
pts.Add(Vector(0,0,0));
CCurve* c2 = new CBSpline(pts,3);

// The Bézier curve object must be deleted automatically
// because the only reference to it has been released
// Similar to IUnknown::Release() in COM
c1 = c2;

Things get a little more complicated when I define surface objects, because some surfaces are defined in terms of two curves:

CVecList pts;
// ...
CCurve* f = new CBezier(pts);

pts.Clear();
// ...
CCurve* g = new CBezier(pts);

// Mixed surface: S(u,v) = (1-v)*f(u) + v*g(u)
CSurface* s = new CMixed(f,g);

// There are two references to the first Bézier curve,
// the first one is f
// the second one is hidden in a member of CMixed

// Something similar applies to the second Bézier curve

, operator = :

// This is what I tried, but it illegal:
typedef CReferenceCounted* PRC;
PRC& operator =(PRC& dest, PRC& source)
{
    if (source)
        source->AddRef();
    if (dest)
        dest->Release();
    memcpy(&dest,&source,sizeof(PRC));
    return dest;
}

... , operator = , .

- ?

+5
5

. ++ , ( , = ). . , , , - , , , . boost::shared_ptr, :

boost::shared_ptr<CCurve> c1(new CBezier(pts));

:

CVecList pts;
// ...
boost::shared_ptr<CCurve> f(new CBezier(pts));

pts.Clear();
// ...
boost::shared_ptr<CCurve> g(new CBezier(pts));

// Mixed surface: S(u,v) = (1-v)f(u) + vg(u)
boost::shared_ptr<CSurface> s(new CMixed(f,g)); 

: , , , . shared_ptr . , . , ++:)

: shared_ptr, pimpl (handle/body):

/* ---- wrapper in header file bezier.hpp */

struct CBezier {
    CBezier(CVecList const& list);
    void do_calc();
    // ...

private:
    struct CBezierImpl;
    boost::shared_ptr<CBezierImpl> p;
};

/* ---- implementation file bezier.cpp */

// private implementation
struct CBezier::CBezierImpl {
    CBezierImpl(CVecList const& list);
    void do_calc();
    // ...
};


CBezier::CBezier(CVecList const& list)
:p(new CBezierImpl(list)) {

}

void CBezier::do_calc() {
    // delegate to pimpl
    p->do_calc();
}

// ...
+11

, , int std:: complex. , . .

std::vector<math::point3d> pts;
pts.push_back(math::point3d(0,0,0));
pts.push_back(math::point3d(110,0,0));
pts.push_back(math::point3d(0,100,0));
pts.push_back(math::point3d(0,0,100));
CCurve c1 = make_bezier(pts);
+1

intrusive_ptr shared_ptr , , intrusive_ptr, .

0

, .

?

, /:

  • /
  • , new/delete
  • .
0

MSalters. , (, vector3 = vector1 + vector2 ..).

, , - copy-on-write (refounting ), . , .

, , , ++ (TNT, ). , ?

0

All Articles