Ответ 1
auto
работает как вывод аргумента шаблона. bar1
и bar2
имеют типы Bar
, поэтому они являются независимыми копиями; bar3
и bar4
имеют тип Bar &
и являются ссылками на тот же *foo.bar
.
У меня есть что-то вроде этого:
class Bar;
class Foo()
{
public:
Foo() : bar(new Bar());
Bar& GetBar() { return *bar.get(); }
private:
std::unique_ptr<Bar> bar;
};
void main()
{
Foo foo;
auto bar1 = foo.GetBar();
auto bar2 = foo.GetBar(); //address of bar2 != address of bar1. why?
Bar& bar3 = foo.GetBar();
Bar& bar4 = foo.GetBar(); //address of bar3 == address of bar4.
}
Кажется, переменные "auto" являются копиями, поскольку я не возвращаю Bars с тем же адресом памяти. Если я явно определяю переменные как ссылки на Bar (Bar &), то все работает так, как я ожидал.
Я должен упомянуть, что я компилирую vs2012. Что здесь происходит?
Спасибо.
auto
работает как вывод аргумента шаблона. bar1
и bar2
имеют типы Bar
, поэтому они являются независимыми копиями; bar3
и bar4
имеют тип Bar &
и являются ссылками на тот же *foo.bar
.
auto bar1 = …
всегда объявляет копию. auto &&bar1
выбирает ближайший возможный ссылочный тип, который вам нужен.
auto &&
- идеальная идиома пересылки.
Вы также можете использовать другие составные типы с auto
, например auto const &
или auto *
, если хотите быть конкретным.
Код:
X& getter() {
static X value;
return value;
}
print("X:");
X x0 = getter();
auto x0a = getter();
x0.printAddress();
x0a.printAddress();
print("X&:");
X& x1 = getter();
auto& x1a = getter();
x1.printAddress();
x1a.printAddress();
print("const X&:");
const X& x2 = getter();
const auto& x2a = getter();
x2.printAddress();
x2a.printAddress();
print("X&&:");
print("Rvalue can't be bound to lvalue");
X&& x3 = getter();
auto&& x3a = getter();
x3.printAddress();
x3a.printAddress();
Результат:
X:
0037F807
0037F7FB
X&:
00D595BA
00D595BA
const X&:
00D595BA
00D595BA
X&&:
Rvalue can't be bound to lvalue
00D595BA
Вывод:
auto
означает: "замените меня типом, если я не auto&&
, а затем найдите наиболее подходящую форму".