C++ 初始化引用时何时以及为什么要获取副本?

C++ 初始化引用时何时以及为什么要获取副本?,c++,reference,C++,Reference,有些情况下,我希望引用一个对象,但却得到了一个副本。 以下是一个例子: std::pair<const std::string, int> foo("hello", 5); const std::pair<std::string, int> & bar = foo; std::cout << "foo: " << foo.first << " " << foo.second << std::

有些情况下,我希望引用一个对象,但却得到了一个副本。 以下是一个例子:

  std::pair<const std::string, int> foo("hello", 5);
  const std::pair<std::string, int> & bar = foo;

  std::cout << "foo: " << foo.first << " " << foo.second << std::endl;
  std::cout << "bar: " << bar.first << " " << bar.second << std::endl;
  foo.second = 7;
  std::cout << "foo: " << foo.first << " " << foo.second << std::endl;
  std::cout << "bar: " << bar.first << " " << bar.second << std::endl;
因此,显然已经创建了一个
foo
的副本,而语法表明(至少对我来说)程序员想要引用它。 这违反了引用应该是某物别名的原则。如果有人能解释发生了什么以及为什么,那就太好了


(注意:我遇到了这一点)

基本类型的
foo
bar
是不同的,因此使用从RHS上的类型到LHS*上的类型的隐式转换来创建临时类型。C++标准允许一个<代码> const 引用绑定到一个临时并延长它的生存期。

const
reference
bar
绑定到该临时对象,该临时对象与
foo
不同

如果使用相同的类型,则会得到预期的结果:

std::pair<const std::string, int> foo("hello", 5);
const std::pair<const std::string, int> & bar = foo;


*
std::pair
有一个允许从一种类型的对到另一种类型的隐式转换的属性。

这是对
常量的引用的特殊属性(当然还有右值引用)。这些引用可以绑定到临时对象

请注意,
std::pair
foo
)的类型与
std::pair
bar
要引用的类型,模
const
)不同。代码中没有类型为
std::pair
的对象,因此
bar
无法绑定到任何此类对象

然而,正如我所说,对
const
和rvalue引用的引用可以绑定到临时变量。并且可以从类型为
std::pair
的对象隐式创建类型为
std::pair
的对象。因此,将创建这样一个临时对象,并将
bar
绑定到该临时对象。此引用绑定还将临时的生存期延长到
bar
*

这就是为什么你会得到一份。如果将
bar
的类型更改为
std::pair&
(即删除
const
),则会出现编译错误,非const左值引用无法绑定到临时变量



*在引用类型的成员变量绑定到临时变量的特殊情况下,临时变量的生存期只会延长到初始化引用的构造函数结束。

类型不同。在哪些情况下,分配不兼容的类型会创建临时变量,而不仅仅是抛出编译器错误?@Sarien中需要在
T1
T2
之间进行有效转换
常数T2&=T1
@Sarien编译器寻找可行的转换。它可以使用原始对中的值的副本调用
pair
的构造函数,这样就可以了。@juanchopanza好的,所以当存在有效转换时,不同类型将导致副本,否则将导致错误。好。现在我明白了,我的案例将导致一个副本,因为它编译并且类型不同。关于这些转换何时存在,我应该从记忆中知道什么吗?为了强调
bar
的示例是相同的类型,可以使用
const auto&bar=foo。这就是关键字的目的,防止不必要的隐式转换。
std::pair<const std::string, int> foo("hello", 5);
const std::pair<const std::string, int> & bar = foo;
std::pair<std::string, int> foo("hello", 5);
const std::pair<std::string, int> & bar = foo;
foo: hello 5
bar: hello 5
foo: hello 7
bar: hello 7