19
#include <vector>

class Object
{
};

int main()
{
    Object myObject;
    std::vector<int> myVector;
}

Compiler emits:

warning: unused variable 'myObject' [-Wunused-variable]

No warning for myVector. Why? Is there any way to enable this?

Jovini
  • 191
  • 4
  • 3
    In C++, constructors and destructors can contain nontrivial logic. So, in general, it's undecidable whether a seemingly unused variable declaration can actually be eliminated. – isekaijin Jun 20 '16 at 08:51
  • 1
    Does it emit the warning when you add a nontrivial zero-parameter constructor to Object? – lorro Jun 20 '16 at 08:52

3 Answers3

24

Whether declaring (and thus initialising and at some point destructung) an arbitrary object has visible side effects cannot be determined in general. The constructor may be calling functions whose definition is not known to the compiler or it may depend on external state or any other aspect which makes the problem undecidable.

In your first case, the constructor is trivial (not even declared), same for the destructor. As Object does not have members, it is clear and easily detectable that Object foo does in fact nothing.

std::vector has a non-trivial constructor which may be allocating memory (external state + function whose definition may not be known (new ...)) together with a non-trivial destructor (also external state + function whose definition may not be known (delete ...)). Reasoning about whether it is safe to remove the declaration (thus emitting a warning hinting that you maybe should) is not possible in this case, thus the compiler has to leave the declaration in the code (and must assume that the declaration is there for a reason).

A prime example is std::lock_guard which is used to lock a mutex when it is constructed and unlock it automatically when it is destructed. The mutex is thus held as long as the object is in scope; generally you would not access the std::lock_guard object at all though—nevertheless it is useful to have it declared. This is the RAII principle at work.

Emitting a warning in such cases would be a nuisance, leading to people turning off the warning, which in turn would render the warning useless. (The compiler may even be designed in such a way that it only emits the warning if it has removed the declaration during optimisation, which is also the reason why some warnings only show up if certain optimisations are enabled.)

Jonas Schäfer
  • 20,140
  • 5
  • 55
  • 69
6

This warning is generated only for trivial types. Compiler is not able to find whether construct will call any external function. If you add a constructor to your Object class then compiler will also issue a warning. Gcc allows to tag types which should generate this warning, you can do this using __attribute__((warn_unused)) :

http://coliru.stacked-crooked.com/a/0130c8ef29c121a1

example:

class __attribute__((warn_unused)) Object
{
    public:
    Object(){}
    void use() {}
};

int main()
{
    Object myObject;  // will give : warning: unused variable 'myObject' [-Wunused-variable]
    //myObject.use(); // uncomment to hide this warning
}

[edit]

from gcc attributes page: https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html :

warn_unused For C++ types with non-trivial constructors and/or destructors it is impossible for the compiler to determine whether a variable of this type is truly unused if it is not referenced. This type attribute informs the compiler that variables of this type should be warned about if they appear to be unused, just like variables of fundamental types. This attribute is appropriate for types which just represent a value, such as std::string; it is not appropriate for types which control a resource, such as std::lock_guard.

This attribute is also accepted in C, but it is unnecessary because C does not have constructors or destructors.

marcinj
  • 48,511
  • 9
  • 79
  • 100
  • 1
    So, should libstdc++ mark most of its types with this attribute? Should they instead have an attribute no_warn_unused for lock and similar types and warn by default? – Marc Glisse Jun 20 '16 at 10:19
  • 2
    @MarcGlisse you are correct (I mean marking 99% of libstdc++), and there is open discussion about this here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55203. – marcinj Jun 20 '16 at 10:40
  • 1
    I agree with Marc, it should be the default behavior. – Jovini Jun 20 '16 at 11:11
2

As well as the answers above, also check your compiler documentation. Some compilers can be set so that they do not show the same warning multiple times. If you comment out the declaration of "myObject", you may then get the same warning for "myVector". With "mObject" producing that warning first, you wouldn't get a warning for "myVector".

Compiler behaviour in the case of warnings is very compiler-specific, so don't assume that all compilers work the same. :)

Graham
  • 1,655
  • 9
  • 19