2016-01-01 9 views

ответ

33

Декларации в точности эквивалентны. auto работает (почти) так же, как template type deduction. Помещение звезды явно упрощает чтение кода, и программист знает, что bar2 является указателем.

5

Не имеет значения, насколько интерпретируется код C++; вы можете писать все, что захотите. Однако возникает вопрос о стиле и читаемости: как правило, вы не должны скрывать указатели, ссылки и квалификаторы CV и, возможно, даже интеллектуальные указатели, в псевдонимах типов, так как это затрудняет понимание читателем, что это то, что происходит. Типичные псевдонимы должны упаковывать семантически релевантный тип содержимого, тогда как классификаторы и модификаторы должны оставаться видимыми. Так предпочитают следующее:

using Foo = long_namespace::Foobrigation<other_namespace::Thing>; 
using MyFn = const X * (int, int); 

std::unique_ptr<Foo> MakeThatThing(MyFn & fn, int x) // or "MyFn * fn" 
{ 
    const auto * p = fn(x, -x); 
    return p ? p->Create() : nullptr; 
} 

И не говори:

using PFoo = std::unique_ptr<Foo>; // just spell it out 
using MyFn = int(&)(int, int);  // unnecessary; & is easy to spell 
auto p = fn(x, -x);     // Don't know that p is a pointer 

Отметим также, что ссылки на Отборочные (в отличие от указателей) действительно изменить тип переменной, которая быть объявлена, поэтому они не являются факультативно:

X & f(); 
auto a = f(); // copy! 
auto & b = f(); // b is the same as the return value of f() 

И, наконец, добавление явных указателей указателя const может помочь const-correctness. Рассмотрим следующий пример, в котором контейнер содержит указатели-to-mutable, но нам нужен только доступ к const. Просто auto * бы вывести указатель на изменяемые, который мы можем избежать, говоря const явно:

std::vector<X*> v = /* ... */; 
for (const auto * p : v) 
{ 
    observe(p->foo()); // no need for a mutable *p 
} 
+0

Как 'MyFn' тип возвращаемого значения является' int', 'Авто * р = п (х, х)' не компилировать (благодаря '*', иначе нам стоит подождать 'p-> Create()' для ошибки) :-). – Jarod42

+0

@ Jarod42: Да, я использовал слишком мало разных сущностей. Исправлена. –

14

В этом конкретном примере, как bar1 и bar2 одинаковы. Это вопрос личных предпочтений, хотя я бы сказал, что bar2 легче читать.

Однако это не относится к ссылкам, как показано в этом example:

#include <iostream> 
using namespace std; 

int main() { 
    int k = 10; 
    int& foo = k; 
    auto bar = foo; //value of foo is copied and loses reference qualifier! 
    bar = 5; //foo/k won't be 5 
    cout << "bar : " << bar << " foo : " << foo << " k : " << k << endl; 
    auto& ref = foo; 
    ref = 5; // foo/k will be 5 
    cout << "bar : " << bar << " foo : " << foo << " k : " << k; 
    return 0; 
} 
35

Использование auto * "документы намерения". И auto *p = expr; можно вывести правильно, только если expr возвращает указатель. Пример:

int f(); 

auto q = f(); // OK 

auto *p = f(); // error: unable to deduce 'auto*' from 'f()' 
+0

Хороший вопрос о запрете выведения без указателей, upvoted. – vsoftco

+2

Да, но следующий оператор & перегружен, чтобы вернуть интеллектуальный указатель notnull или const, а затем автоматически * ломается. –

10

Как уже было сказано, они будут генерировать тот же код. Звездочка представляет собой линейный шум (и затрудняет переход от необработанных указателей к интеллектуальным указателям, если, например, &foo заменяется на get_foo()). Если вы хотите быть явным, то, во всяком случае, быть явным; но когда вы используете вывод типа, просто дайте компилятору выполнить свою работу. Отсутствие звездочек не означает, что объект не является указателем.

+3

Я думаю, что комментарий в круглых скобках заслуживает большего внимания. Даже в простых примерах, которые дали другие, добавление '*' может сделать код более читаемым, но может затруднить обслуживание. Я лично считаю, что основным преимуществом 'auto' является облегчение обслуживания, даже более того, чем сокращение набора текста или повышение удобочитаемости. – ToddR

8

Существует большая разница, когда вы используете const классификаторов:

int i; 

// Const pointer to non-const int 
const auto ip1 = &i; // int *const 
++ip1; // error 
*ip1 = 1; // OK 

// Non-const pointer to const int 
const auto* ip2 = &i; // int const* 
++ip2; // OK 
*ip2 = 1; // error