C++ ';自动';和显式变量声明的行为不同

C++ ';自动';和显式变量声明的行为不同,c++,c++11,C++,C++11,我有这样的想法: 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(); //

我有这样的想法:

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.
}
类条;
类别Foo()
{
公众:
Foo():条(新条());
Bar&GetBar(){return*Bar.get();}
私人:
std::唯一的ptr条;
};
void main()
{
富富,;
auto bar1=foo.GetBar();
auto bar2=foo.GetBar();//bar2的地址!=bar1的地址。为什么?
Bar&bar3=foo.GetBar();
Bar&bar4=foo.GetBar();//bar3的地址==bar4的地址。
}
“auto”变量似乎是副本,因为我没有得到具有相同内存地址的条。 如果我显式地将变量定义为条引用(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
结果:

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
结论:

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
的意思是:“用type替换我,除非我是
auto&
,然后找到最合适的表单”。

但是GetBar()返回一个Bar&我可以想象auto会将变量设置为函数的返回类型。无论如何,我在这里找到了解释:在标题为:Auto、References、Pointers和Const的部分。这有点奇怪。@Aeluned:你可以想象你想要的一切,但事实是,
auto
的工作原理类似于模板参数推断。当你有
模板空f(T)并调用
f(foo.getBar())
,您将推断出
T=Bar
…@aelunend:在许多情况下,您可能不希望这样做,例如,当访问对象中的字段时,如果访问器返回一个常量引用,则您希望立即获取该值,而不是对可能更改的值的引用。当前规范允许您通过添加
&
来选择是否需要引用,就像在
auto&bar3=…
+1中一样,我不知道
auto
是否引用了折叠以及模板类型参数。@SethCarnegie-Yep,我所有的变量中有很大一部分是声明的
auto&&
…这几乎是我的默认值:)这也让我感到困惑,所以一些好的ppl解决了我的问题:):