C++ C++;11自动和功能返回类型

C++ C++;11自动和功能返回类型,c++,c++11,type-inference,C++,C++11,Type Inference,我知道auto、auto&、const auto和const auto&之间的区别(例如在“for each”循环中),但让我吃惊的是: std::string bla; const std::string& cf() { return bla; } int main (int argc, char *argv[]) { auto s1=cf(); const std::string& s2=cf(); s1+="XXX"; // not an

我知道
auto
auto&
const auto
const auto&
之间的区别(例如在“for each”循环中),但让我吃惊的是:

std::string bla;
const std::string& cf()
{
    return bla;
}


int main (int argc, char *argv[])
{
    auto s1=cf();
    const std::string& s2=cf();
    s1+="XXX"; // not an error
    s2+="YYY"; //error as expected
}

那么有人能告诉我表达式
auto x=fun()中
x的类型是什么时候吗的类型与
fun()

的返回值的类型不同
自动的规则与模板类型推断的规则相同:

template <typename T>
void f(T t); // same as auto
template <typename T>
void g(T& t); // same as auto&
template <typename T>
void h(T&& t); // same as auto&&

std::string sv;
std::string& sl = sv;
std::string const& scl = sv;

f(sv); // deduces T=std::string
f(sl); // deduces T=std::string
f(scl); // deduces T=std::string
f(std::string()); // deduces T=std::string
f(std::move(sv)); // deduces T=std::string

g(sv); // deduces T=std::string, T& becomes std::string&
g(sl); // deduces T=std::string, T& becomes std::string&
g(scl); // deduces T=std::string const, T& becomes std::string const&
g(std::string()); // does not compile
g(std::move(sv)); // does not compile

h(sv); // deduces std::string&, T&& becomes std::string&
h(sl); // deduces std::string&, T&& becomes std::string&
h(scl); // deduces std::string const&, T&& becomes std::string const&
h(std::string()); // deduces std::string, T&& becomes std::string&&
h(std::move(sv)); // deduces std::string, T&& becomes std::string&&
模板
空隙f(T);//和汽车一样
模板
无效g(T&T);//和汽车一样&
模板
无效h(T&T);//和汽车一样&&
std::字符串sv;
std::string&sl=sv;
std::string const&scl=sv;
f(sv);//推断T=std::string
f(sl);//推断T=std::string
f(scl);//推断T=std::string
f(std::string());//推断T=std::string
f(std::move(sv));//推断T=std::string
g(sv);//推导出T=std::string,T&成为std::string&
g(sl);//推导出T=std::string,T&成为std::string&
g(scl);//推导出T=std::string const,T&变成std::string const&
g(std::string());//不编译
g(std::move(sv));//不编译
h(sv);//推断std::string&,T&&成为std::string&
h(sl);//推断std::string&,T&&成为std::string&
h(scl);//推导std::string const&,T&&成为std::string const&
h(std::string());//推导std::string,T&&成为std::string&&
h(标准::移动(sv));//推导std::string,T&&成为std::string&&

通常,如果您想要副本,请使用
auto
,如果您想要引用,请使用
auto&
auto&
保留引用的常量,还可以绑定到临时对象(延长其生存期)。

在g++-4.8中,有一个对函数返回类型自动推断的增强功能:

2012-03-21杰森·梅里尔

Implement return type deduction for normal functions with -std=c++1y.
您需要-std=c++1y或-std=gnu++1y标志

这项工作: 汽车 sluggo() { 返回42; }

OP问题错误仅在
+=“YYY”
上显示,如预期的那样。您甚至可以使用auto声明cf:

#include <string>

std::string bla;

const auto&
cf()
{
    return bla;
}


int
main()
{
    auto s1 = cf();
    const std::string& s2 = cf();
    s1 += "XXX"; // not an error
    s2 += "YYY"; // error as expected
}
#包括
std::字符串bla;
常数自动&
cf()
{
返回bla;
}
int
main()
{
自动s1=cf();
常量std::string&s2=cf();
s1+=“XXX”;//不是错误
s2+=“YYY”;//预期错误
}

它仍然在
+=“YYY”

@nosenseal上出错,因为函数
f
也会推断出这一点(顶级
const
在参数中并不重要)。我用const@nosensetal添加了一个示例,但由于
auto
变成了
std::string
,它将生成一个本地副本,因此实际上没有问题(除非您不知道这一点,可能会感到意外)。在您的代码中,
s1+=“XXX”
正在更改本地副本,而不是函数结果引用的对象。请注意
g(scl)
h(scl)
如何推断对常量的引用:非顶级常量(这才是真正重要的)始终被保留。哦,是的,它不会删除常量,而是删除常量和&。这使得它不那么难看,但仍然令人不快(如果返回值是要修改的…)。赫伯的“随时随地使用汽车”到此为止。。。不管是哪种方式,tnx都可以解决这个问题?IDK,如果它是OT,但是你知道汽车还有其他问题吗?我知道表达式模板有一些问题,但这些东西对我来说太复杂了。()@nosensetal如果你想要一个好的经验法则,我喜欢“如果你想要一份副本,使用
auto
,如果你想要一份参考,使用
auto&
”。后者保留了所有内容,是我在默认情况下使用的,例如,循环范围。@nosenseal技术上,因为
void-fun(int)
无效乐趣(int const)声明相同的函数(请参阅):调用方不关心函数是否更改了自己的局部参数副本;规则与模板类型推断相同。但这也是大多数时候有意义的。如果我想制作一份本地拷贝,大多数时候我不想要它。如果您真的需要const本地副本,您可以始终使用
auto const
。请不要将答案编辑到您的问题中,即使是作为代码中的注释。这会使未来的读者无法理解你的问题,就像你遇到问题时一样。我已回滚您的编辑以修复此问题。:)我看不出C++1y与我的问题有什么关系,尤其是在C++17中?s1仍然是“std::string”类型,我想现在不会有帮助了。但看起来函数类型推断将在以后标准化。我猜你的失败是“故意的”。但其他人认为这种设计过于严格,正在努力解决它。
#include <string>

std::string bla;

const auto&
cf()
{
    return bla;
}


int
main()
{
    auto s1 = cf();
    const std::string& s2 = cf();
    s1 += "XXX"; // not an error
    s2 += "YYY"; // error as expected
}