2012-03-18 4 views
6

Compiling этого кода с г ++ 4.7.0 (-Wall -Wextra -Werror -Wconversion -std=c++11):Uniform инициализации с {} отчетов неиспользованных переменной

#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

Что происходит во время выполнения, если вы используете «плохую» версию кода и компилируете без «-Werror»? –

+0

@JohnZwinck ** ошибка ** превращается в ** предупреждение ** –

+0

Похоже, что это просто необработанный случай в логике предупреждения неиспользуемой переменной. Введите ошибку с gcc. – bames53

ответ

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()); 

DECLARE bar в Foo или Foo&&, который подавляет предупреждение, поскольку он имеет нетривиальные специальные функции-члены.

Обычно вы не хотите, чтобы начальная инициализация была с auto, если вы специально не намереваетесь создать объект std::inializer_list.

+0

Это имеет смысл. Я ошибочно предполагал, что GCC будет использовать 'Foo' как тип, когда на самом деле у него нет причин. –

+1

На самом деле, я попробовал 'auto bar {5}; cout << typeid (bar) << endl; 'и выводит' St16initializer_listIiE', поэтому вы определенно верны! –

2

Ну, barесть не использовался. Возможно, вы захотите записать дефект для компилятора, поскольку это, по-видимому, ошибочно остается незамеченным в других ситуациях.

+2

'bar' не используется, но я думал, что компилятор не сообщил о неиспользуемых переменных предупреждениях для нетривиальных типов. –

+0

Независимо от того, что компилятор использует для создания предупреждений, зависит от компилятора! Моя личная позиция заключается в том, что я хочу, чтобы все неиспользуемые переменные были отмечены, когда я прошу об исключении неиспользуемых переменных. В моем наборе инструментов у меня есть простой шаблон функции для случаев, когда я подразумеваю, что объекты не используются: 'template void use (T const &) {}'. –

 Смежные вопросы

  • Нет связанных вопросов^_^