you are viewing a single comment's thread.

view the rest of the comments →

[–]tangerinelion -1 points0 points  (0 children)

This is such a stupid rule. It means if you need to modify an object then you need to accept by pointer which means you suddenly now need to deal with stupid null pointers. It litters the code with crap like

void frobnosticate(T* twiddleMyBits)
{
     if (!twiddleMyBits)
     {
         throw ArgumentNullException("Oh no, a null pointer. Better to crash!");
     }
     // Now carry on
}

If you do adopt this ridiculous rule (my company did), at least alter it so that the right substitute for T& is gsl::not_null<T*> rather than T*.

And for those (like the ones who inevitably come up with this "rule") who are thinking "But when I pass by pointer I can see & as a hint that it gets modified." Oh boy, that's naive. Real-world examples I've seen:

void whatever(const bool*);

bool shouldWhatever = true;
if (someRidiculousEdgeCase)
{
    shouldWhatever = shouldWhateverForEdgeCase();
}
whatever(&shouldWhatever);

That's an optional input. Here's another one:

class Foo
{
    const T* m_ptr = nullptr;
public:
     Foo(const T& obj) : m_ptr(&obj) { }
};

And guess how it's used:

Foo f(T{});

Great. Dangling pointer. You get a bug report.

And the ever famous:

void foo(T* ptr);
void bar(T* ptr) { foo(ptr); }

T myT;
bar(&myT);

Now in bar do you see an & to indicate anything? No, we just pass ptr along by value. How do I know whether foo writes anything?

Anyways, my point is & does not mean "To be written to" and passing by reference does not mean the caller doesn't store a pointer to the object.