C++ 11自动和函数返回类型

NoS*_*tAl 5 c++ type-inference c++11

我知道之间的区别的auto,auto&,const autoconst auto&(例如在"每个"循环),但有一两件事令我惊讶的是:

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
}
Run Code Online (Sandbox Code Playgroud)

那么有人可以告诉我何时x表达式auto x = fun();中的类型与返回值的类型不是同一类型fun()

R. *_*des 18

规则auto与模板类型推导相同:

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&&
Run Code Online (Sandbox Code Playgroud)

通常,如果您需要副本,则使用auto,如果您需要使用的引用auto&&.auto&&保留referene的常量,也可以绑定临时(延长其寿命).

  • @NoSenseEtAl技术上,因为`void fun(int);`和`void fun(int const);`声明相同的函数(参见http://ideone.com/l6yZu):调用者不关心函数是否改变它自己的本地参数副本; 并且规则与模板类型推导相同.但它也是大部分时间都有意义的东西.如果我想制作本地副本,大多数时候我不想要它.如果你真的想要一个const本地副本,你总是可以使用`auto const`. (3认同)
  • @NoSenseEtAl但是因为`auto`变成`std :: string`,它会产生一个本地*副本*,所以实际上没有问题(除了你可能没有意识到的可能的惊喜).在你的代码中`s1 + ="XXX"`正在改变本地副本,而不是函数结果引用的对象.注意`g(scl)`和`h(scl)`如何推导出对const的引用:非顶级const(这才是真正重要的)总是被保留. (2认同)
  • @NoSenseEtAl如果你想要一个好的经验法则,我喜欢"如果你想要一个副本就使用`auto`,如果你想要一个参考,你可以使用`auto &&`".后者保留了所有内容,是我默认使用的内容,例如,ranged-for循环. (2认同)