Compiling this code with g++ 4.7.0 (-Wall -Wextra -Werror -Wconversion -std=c++11
):
#include <iostream> // std::cout, std::endl
#include <string> // std::string
#include <utility> // std::move
void out(std::string const &message)
{
static int count{0};
std::cout << count++ << " = " << message << std::endl;
}
struct Foo
{
Foo() {out("constructor");}
~Foo() {out("destructor");}
Foo(Foo const &) {out("copy constructor");}
Foo & operator=(Foo const &) {out("copy via assignment"); return *this;}
Foo(Foo &&) {out("move constructor");}
Foo & operator=(Foo &&) {out("move via assignment"); return *this;}
};
int main()
{
auto bar{std::move(Foo())};
out("exiting main");
}
...results in the following error:
error: unused variable 'bar' [-Werror=unused-variable]
I can remove the error by changing the bar
initialization to any of the following:
/* 0 */ auto bar(std::move(Foo()));
/* 1 */ Foo bar{std::move(Foo())};
/* 2 */ Foo bar(std::move(Foo()));
/* 3 */ auto bar = std::move(Foo());
/* 4 */ Foo bar = std::move(Foo());
/* 5 */ auto bar __attribute__((unused)) {std::move(Foo())};
Once the bar
initialization has been changed, the output is always:
0 = constructor
1 = move constructor
2 = destructor
3 = exiting main
4 = destructor
Why does the original bar
initialization report an unused variable?
Uniform initialization is a feature in C++ 11 that allows the usage of a consistent syntax to initialize variables and objects ranging from primitive type to aggregates. In other words, it introduces brace-initialization that uses braces ({}) to enclose initializer values.
An unused variable refers to a variable of which the data element structure is unreferenced in the main program, including the parent and the subordinate items. An unused copybook refers to a copybook with the aforementioned copybook of an unused variable.
auto bar{std::move(Foo())};
After this declaration, bar
is of type std::initializer_list<Foo>
, which has trivial copy/move operations and destructor. Your other declarations
auto bar(std::move(Foo()));
Foo bar{std::move(Foo())};
Foo bar(std::move(Foo()));
auto bar = std::move(Foo());
Foo bar = std::move(Foo());
declare bar
as Foo
or Foo&&
, which suppresses the warning since it has nontrivial special member functions.
You generally don't want braced initialization with auto
unless you specifically intend to create a std::inializer_list
object.
Well, bar
is unused. You may want to file a defect for the compiler as this seems to errornously go undetected in the other situations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With