0

This is how my company implements reference counting objects in C++:

    #ifndef DECLARE_REF_COUNT
    #define DECLARE_REF_COUNT \
    public: \
        void Ref() { atomic_inc(_refs); } \
        void UnRef() { \
            int n = atomic_dec(_refs); \
            if (n <= 0) { \
                delete this; \
            } \
        } \
    private: \
        volatile int _refs;
    #endif

So when you need to create a reference counting class, you do:

class MyClass {
DECLARE_REF_COUNT;
public:
         ...
};

When you use it, you do:

myobj->Ref();
...
myobj->UnRef();

I have proposed using shared pointer to my leader, as it doesn't need to Ref and UnRef manually, but my leader prefers the Macro way and he told me that we won't forget to call UnRef() because it's so basic and we don't hire those who will forget to do this. Another reason he prefers using Macro is because it give more control when some explicit Ref and UnRef is needed. So suppose no boost and no c++11, is Macro a good way to do so? And what's the advantage and disadvantage of this way?

bugs king
  • 566
  • 5
  • 13
  • 1
    You should submit this to http://thedailywtf.com. In a sane company, the reference count and all these methods will be a superclass, and any class that wants to be reference-counted will simply inherit from it. – Sam Varshavchik Aug 26 '16 at 15:12
  • 5
    "we don't hire those who will forget to do this" This is a common euphemism for "I don't care about your argument". No logical argument is going to make your boss change his mind, so just do it. – Sergey Kalinichenko Aug 26 '16 at 15:13
  • 2
    I don't think `volatile` is doing anything to help you here. See http://stackoverflow.com/q/8819095/10077 – Fred Larson Aug 26 '16 at 15:15
  • 1
    @SamVarshavchik except for times when you don't want to inherit at all, or you would rather avoid multiple inheritance "diamond", or you are writing a template class, etc. The solution shown by OP is screwed up, but inheriting does not give you a universal solution either. Smart pointers are close to ideal, because they don't force you to pollute your code with ref/unref calls. – Sergey Kalinichenko Aug 26 '16 at 15:19
  • @dasblinkenlight - I'm confused, how exactly was I able to solve the diamond inheritance problem using my reference counting superclass, which also does not require explicit ref/unref calls, either? – Sam Varshavchik Aug 26 '16 at 15:56
  • @SamVarshavchik If even you don't know "how exactly you were able to solve it", how do you expect me to know it? After all, I wasn't the one to suggest that you offered a solution, was I? – Sergey Kalinichenko Aug 26 '16 at 16:04
  • @dasblinkenlight - it just seemed fairly obvious to me. Virtual inheritance and all ref counting in the superclass's constructor(s) and destructor. – Sam Varshavchik Aug 26 '16 at 16:08
  • Ahh, good old not understanding `volatile` :) http://stackoverflow.com/questions/6627596/is-volatile-int-in-c-as-good-as-stdatomicint-of-c0x. Also, shared_ptr also has the ability to early unref. Lastly, if you are smart enough not to forget to ref/unref things manually, your time is better invested in the hard stuff. – kfsone Aug 26 '16 at 19:54
  • Macro is an absolute obsolete manner! Make new programs in modern technic! – Roland Sep 02 '16 at 07:44

1 Answers1

1

If everyone was as qualified as your leader, we wouldn't have needed to create smart pointers.

But, alas, we did.

I would recommend a base class over macros through.

class RefCounted
{
public:
   void Ref() { ... }
   void UnRef() { ... }
private:
   volatile int _refs;
}


class MyClass : public RefCounted

Also one of the core tenets of c++11 and beyond is reducing the need for manual resource management. Things like std::shared_ptr and std::unique_ptr were created to solve exactly this problem. RAII classes can be written without C++11 as well, and are strongly recommended.

lcs
  • 4,227
  • 17
  • 36
  • 1
    "we wouldn't have needed to create smart pointers" - But we would still want to, because manual calls to `UnRef` clutter the code and obscure the actual intent. The boss is clearly not as qualified as he thinks if he prefers writing useless code to doing the easy thing. – Sebastian Redl Aug 26 '16 at 15:21
  • @SebastianRedl Fair enough. I was just referring to the leaders claims that calling `UnRef` is so easy nobody would ever miss it. – lcs Aug 26 '16 at 15:22
  • 1
    I know. I was just making the point that even if the boss's statement wasn't absurd, the smart pointer is still the better choice. – Sebastian Redl Aug 26 '16 at 15:26
  • You might place the destructor protected. – Jarod42 Aug 26 '16 at 15:42
  • @Jarod42 The description mentions no `c++11`, which defines `std::atomic`. I agree about the destructor, but they may have to use platform specific atomic implementations. – lcs Aug 26 '16 at 15:45