使用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");
}
...导致以下错误:
error: unused variable 'bar' [-Werror=unused-variable]
我可以通过将bar
初始化更改为以下任何一项来删除错误:
/* 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())};
更改bar
初始化后,输出始终:
0 = constructor
1 = move constructor
2 = destructor
3 = exiting main
4 = destructor
为什么原始bar
初始化会报告未使用的变量?
答案 0 :(得分:8)
auto bar{std::move(Foo())};
在此声明之后,bar
的类型为std::initializer_list<Foo>
,它具有简单的复制/移动操作和析构函数。你的其他声明
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());
将bar
声明为Foo
或Foo&&
,因为它具有非常重要的特殊成员函数,所以会禁止警告。
除非您特意打算创建auto
对象,否则通常不希望使用std::inializer_list
进行支持初始化。
答案 1 :(得分:2)
好吧,bar
未使用。您可能希望为编译器提交缺陷,因为在其他情况下这似乎错误地未被发现。