Understanding -Weffc++

2019-01-14 17:42发布

问题:

Consider the following program:

#include <string>

struct S {
    S (){}

private:
    void *ptr = nullptr;
    std::string str = "";
};

int main(){}

This, when compiled with -Weffc++ on GCC 4.7.1, will spit out:

warning: 'struct S' has pointer data members [-Weffc++]
warning:   but does not override 'S(const S&)' [-Weffc++]
warning:   or 'operator=(const S&)' [-Weffc++]

That's no problem normally, except for a couple things with this example:

  1. If I comment out any of the constructor, the pointer declaration, or the string declaration, the warning disappears. This is odd because you'd think the pointer alone would be enough, but it isn't. Furthermore, changing the string declaration to an integer declaration causes it to disappear as well, so it only comes up when there's a string (or probably other choice classes) with it. Why does the warning disappear under these circumstances?

  2. Often times this warning comes up when all the pointer is doing is pointing to an existing variable (most often maintained by the OS). There's no new, and no delete. When the class with the handle, in these cases, is copied, I don't want a deep copy. I want both handles to point to the same internal object (like a window, for example). Is there any way to make the compiler realize this without unnecessarily overloading the copy constructor and assignment operator, or disabling the warning completely with #pragma? Why am I being bothered in the first place when the Rule of Three doesn't even apply?

回答1:

  1. When you do it, you have a POD structure. As it cannot have any constructors, -Weffc++ doesn't bother checking.

  2. Use a reference or shared_ptr object or any other object that wrap a pointer.



回答2:

GCC's -Weffc++ has several issues, I never use it. The code that checks for "problems" is pretty simplistic and so the warnings end up being far too blunt and unhelpful.

That particular warning is based on Item 11 of the first edition of Effective C++ and Scott changed it (for the better) in later editions. The G++ code doesn't check for actual dynamic allocation, just the presence of pointer members.

See what I wrote about this warning in GCC's bugzilla when comparing the guidelines in the first edition with the third edition:

Item 11: Define a copy constructor and an assignment operator for classes with dynamically allocated memory.

Replaced by Item 14: "Think carefully about copying behavior in resource-managing classes" - the advice is less specific, but more useful. I'm not sure how to turn it into a warning though!