C++ gcc 4.9.1约束a c和#x2B+;局部变量到常量自动引用

C++ gcc 4.9.1约束a c和#x2B+;局部变量到常量自动引用,c++,c++11,gcc,c++14,C++,C++11,Gcc,C++14,我发现最令人讨厌的绑定问题似乎是特定于GCC的。我不确定这是否是我不理解const auto&绑定的规则,或者问题是否指向gcc编译器特定的bug。相比之下,VisualStudio 2015的C++编译器(更新2作为本文的撰写)没有表现出这种不可预测的行为。我能够用极简主义的方法重现这个问题 如果我将自动变量绑定到“const auto&”,就会出现问题。在本例中,const auto&bind变量似乎绑定到垃圾。如果这是一个用户错误(我不理解规则),有人能解释一下我应该如何做以避免这种意外行

我发现最令人讨厌的绑定问题似乎是特定于GCC的。我不确定这是否是我不理解
const auto&
绑定的规则,或者问题是否指向gcc编译器特定的bug。相比之下,VisualStudio 2015的C++编译器(更新2作为本文的撰写)没有表现出这种不可预测的行为。我能够用极简主义的方法重现这个问题

如果我将自动变量绑定到“const auto&”,就会出现问题。在本例中,
const auto&
bind变量似乎绑定到垃圾。如果这是一个用户错误(我不理解规则),有人能解释一下我应该如何做以避免这种意外行为的规则吗。现场演示展示了一个我遇到错误的例子,我不确定这个问题是否会发生在其他地方,因为我倾向于尽可能使用
const auto&
绑定

OptPairWrapper wrapper;
wrapper.setOptPair(std::make_pair(1,2));
const auto& badConstAutoRefBind = wrapper.getOptPair().get();
const auto goodConstAutoBind = wrapper.getOptPair().get();
// This line prints garbage
std::cout << badConstAutoRefBind << std::endl;  
// This line predictably prints (1,2)
std::cout << goodConstAutoBind << std::endl;  

这与
auto
无关

const
引用可以延长它们绑定到的临时对象的生存期。但是,这仅在直接绑定临时文件时有效:

int foo() { ... }

int main() {
    int const &i = foo(); // Fine
}

在您的示例中,调用
boost::optional
get()
函数,该函数返回左值引用。此引用不是临时引用,因此不会延长生存期。

这与
auto
无关

const
引用可以延长它们绑定到的临时对象的生存期。但是,这仅在直接绑定临时文件时有效:

int foo() { ... }

int main() {
    int const &i = foo(); // Fine
}

在您的示例中,调用
boost::optional
get()
函数,该函数返回左值引用。此引用不是临时引用,因此不会延长生存期。

如果
boost::optional::get()
返回对其成员的左值引用,则它是该临时引用的子对象,因此完整对象的生存期也应该延长,不是吗?@PiotrSkotnicki这确实非常方便,但不幸的是,情况并非如此。考虑一个(非模板)类,具有这样的<代码> GET()/<代码>函数:没有办法知道返回引用是否从外部绑定到临时<代码> *这个< /代码>。您只能通过直接命名外部对象的一个成员来延长外部对象的生命周期。@Quentin回答得很好,但我仍然有点困惑,因为我不知道为什么goodConstAutoBind在我的示例中起作用-boost::optional::get()的返回值是(1)“reference\u const\u type get()const”或“reference\u type get()(假定为非常量)”“-我在boost::optional的源代码中看到了这一点。这难道不意味着我的const auto&-绑定到这两种可能的返回类型中的第一种,第二种绑定到工作赋值吗?不管怎么说,真正让我困惑的是,为什么在我的演示中省略&似乎成功地返回了正确的东西?@johnco3-sure-thing<代码>自动的工作原理与函数模板参数推导类似。所发生的事情是,它推导初始值设定项的类型,忽略顶级常量和引用。然后,您可以为新变量选择这些值。因此,
auto-const&
生成一个
const
引用,而
auto
生成一个值,该值实际上是从初始值设定项构造的copy-(或move-)。初始化器中对象的命运是不相关的,因为你有它的副本。如果
boost::optional::get()
返回对其成员的左值引用,那么它是该临时对象的子对象,所以完整对象的生存期也应该延长,不是吗?@PiotrSkotnicki这确实非常方便,但不幸的是,情况并非如此。考虑一个(非模板)类,具有这样的<代码> GET()/<代码>函数:没有办法知道返回引用是否从外部绑定到临时<代码> *这个< /代码>。您只能通过直接命名外部对象的一个成员来延长外部对象的生命周期。@Quentin回答得很好,但我仍然有点困惑,因为我不知道为什么goodConstAutoBind在我的示例中起作用-boost::optional::get()的返回值是(1)“reference\u const\u type get()const”或“reference\u type get()(假定为非常量)”“-我在boost::optional的源代码中看到了这一点。这难道不意味着我的const auto&-绑定到这两种可能的返回类型中的第一种,第二种绑定到工作赋值吗?不管怎么说,真正让我困惑的是,为什么在我的演示中省略&似乎成功地返回了正确的东西?@johnco3-sure-thing<代码>自动的工作原理与函数模板参数推导类似。所发生的事情是,它推导初始值设定项的类型,忽略顶级常量和引用。然后,您可以为新变量选择这些值。因此,
auto-const&
生成一个
const
引用,而
auto
生成一个值,该值实际上是从初始值设定项构造的copy-(或move-)。初始化器中对象的命运与此无关,因为您有它的副本。您正试图使用对已销毁临时值的引用。不要害怕按值返回:在大多数情况下
const Class var=someMethod()将通过复制省略而不是复制/移动构造函数或赋值运算符进行优化。您正在尝试使用对已销毁临时值的引用。不要害怕按值返回:在大多数情况下
const Class var=someMethod()将通过复制省略而不是复制/移动构造函数或赋值运算符进行优化。