为什么“自动”和显式引用变量声明的行为不同?

问题描述 投票:0回答:3

我有这样的东西:

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.
}

“自动”变量似乎是副本,因为我没有得到具有相同内存地址的 Bars。 如果我将变量显式定义为 Bar 引用 (Bar&),那么一切都会按我的预期工作。

我应该提到我是在 vs2012 中编译的。这是怎么回事?

谢谢。

c++ c++11 reference auto
3个回答
22
投票

auto bar1 = …
始终声明副本。
auto &&bar1
选择最接近的可能参考类型,这就是您想要的。

auto &&
完美转发的习语。

您还可以将其他复合类型与

auto
一起使用,例如
auto const &
auto *
(如果您想具体)。


13
投票

auto
的工作方式类似于模板参数推导。
bar1
bar2
都有类型
Bar
,所以它们是独立的副本;
bar3
bar4
具有类型
Bar &
并且是对相同
*foo.bar
的引用。


1
投票

代码:

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&&
然后找到最合适的形式
”。

© www.soinside.com 2019 - 2024. All rights reserved.