C++11 auto:如果它获得常量引用怎么办?

发布于 2024-11-30 16:05:32 字数 738 浏览 3 评论 0原文

请看一下下面的简单代码:

class Foo
{
public:
  Foo(){}
  ~Foo(){}

  Foo(const Foo&){}
  Foo& operator=(const Foo&) { return *this; }
};

static Foo g_temp;
const Foo& GetFoo() { return g_temp; }

我尝试像这样使用 auto

auto my_foo = GetFoo();

我期望 my_foo 将是对 Foo 的常量引用,这是函数的返回类型。但是,auto 的类型是 Foo,而不是引用。此外,my_foo 是通过复制g_temp 创建的。这种行为对我来说并不那么明显。

为了获得对 Foo 的引用,我需要这样写:

const auto& my_foo2 = GetFoo();
      auto& my_foo3 = GetFoo();

问题:为什么 auto 推导出 的返回类型GetFoo 作为对象,而不是引用?

Please take a look at the following simple code:

class Foo
{
public:
  Foo(){}
  ~Foo(){}

  Foo(const Foo&){}
  Foo& operator=(const Foo&) { return *this; }
};

static Foo g_temp;
const Foo& GetFoo() { return g_temp; }

I tried to use auto like this:

auto my_foo = GetFoo();

I expected that my_foo will be a constant reference to Foo, which is the return type of the function. However, the type of auto is Foo, not the reference. Furthermore, my_foo is created by copying g_temp. This behavior isn't that obvious to me.

In order to get the reference to Foo, I needed to write like this:

const auto& my_foo2 = GetFoo();
      auto& my_foo3 = GetFoo();

Question: Why does auto deduce the return type of GetFoo as an object, not a reference?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

背叛残局 2024-12-07 16:05:32

阅读这篇文章:C++ 中出现和消失的常量


C++0x 中自动变量的类型推导本质上与
对于模板参数。 (据我所知,唯一的区别
两者之间的区别是自动变量的类型可以从
初始值设定项列表,而模板参数的类型可能不是。)
因此,以下每个声明都声明类型的变量
int(从不 const int):

auto a1 = i;
auto a2 = ci;
auto a3 = *pci;
auto a4 = pcs->i;

仅在模板参数和自动变量的类型推导期间
顶级常量被删除。给定一个函数模板
指针或引用参数,所指向的内容的常量
或提及的内容被保留:

template<typename T>
void f(T& p);

int i;
const int ci = 0;
const int *pci = &i;

f(i);               // as before, calls f<int>, i.e., T is int
f(ci);              // now calls f<const int>, i.e., T is const int
f(*pci);            // also calls f<const int>, i.e., T is const int

此行为已是旧闻,适用于 C++98 和
C++03。当然,自动变量的相应行为是:
C++0x 新手:

auto& a1 = i;       // a1 is of type int&
auto& a2 = ci;      // a2 is of type const int&
auto& a3 = *pci;    // a3 is also of type const int&
auto& a4 = pcs->i;  // a4 is of type const int&, too

由于如果类型是引用或指针,您可以保留 cv 限定符,因此您可以这样做:

auto& my_foo2 = GetFoo();

而不必将其指定为 const (对于 也是如此)易失性)。

编辑:至于为什么 autoGetFoo() 的返回类型推导出为值而不是引用(这是您的主要问题,抱歉),考虑一下:

const Foo my_foo = GetFoo();

上面的代码将创建一个副本,因为 my_foo 是一个值。如果 auto 返回左值引用,则上述情况将不可能实现。

Read this article: Appearing and Disappearing consts in C++


Type deduction for auto variables in C++0x is essentially the same as
for template parameters. (As far as I know, the only difference
between the two is that the type of auto variables may be deduced from
initializer lists, while the types of template parameters may not be.)
Each of the following declarations therefore declare variables of type
int (never const int):

auto a1 = i;
auto a2 = ci;
auto a3 = *pci;
auto a4 = pcs->i;

During type deduction for template parameters and auto variables, only
top-level consts are removed. Given a function template taking a
pointer or reference parameter, the constness of whatever is pointed
or referred to is retained:

template<typename T>
void f(T& p);

int i;
const int ci = 0;
const int *pci = &i;

f(i);               // as before, calls f<int>, i.e., T is int
f(ci);              // now calls f<const int>, i.e., T is const int
f(*pci);            // also calls f<const int>, i.e., T is const int

This behavior is old news, applying as it does to both C++98 and
C++03. The corresponding behavior for auto variables is, of course,
new to C++0x:

auto& a1 = i;       // a1 is of type int&
auto& a2 = ci;      // a2 is of type const int&
auto& a3 = *pci;    // a3 is also of type const int&
auto& a4 = pcs->i;  // a4 is of type const int&, too

Since you can retain the cv-qualifier if the type is a reference or pointer, you can do:

auto& my_foo2 = GetFoo();

Instead of having to specify it as const (same goes for volatile).

Edit: As for why auto deduces the return type of GetFoo() as a value instead of a reference (which was your main question, sorry), consider this:

const Foo my_foo = GetFoo();

The above will create a copy, since my_foo is a value. If auto were to return an lvalue reference, the above wouldn't be possible.

旧瑾黎汐 2024-12-07 16:05:32

您可以采用 MSVC 技术文档

使用自动删除引用、常量限定符和易失性
预选赛。

您不需要函数来实现类似的结果。考虑:

int var;
const int & cref = var;
auto avar = cref;

avar 的类型将是 int,而不是 const int &int &

要更深入地了解这一点,我们可以访问 cppreference.com 并参考与模板参数推导类比。

例如,给定 const auto& i = expr;i 的类型正是假想模板 template中参数 u 的类型。 void f(const U&u).

我们倾向于直观地使用模板,在它起作用之前我们从来不会真正关心模板参数推导规则。这些规则实际上相当复杂。但是我们可以将“auto 的虚构模板”设为非虚构,并测试如果我们向模板提供 auto i = expr; 会发生什么。在我们的例子中,模板可能如下所示:

template<class U> 
void f(U u)
{
    cout << type_name<decltype(u)>() << "\n";
}

让我们向它提供我们感兴趣的类型的变量:

    int i = 0;
    int & ir = i;
    const int & cir = i;
    f(i);
    f(ir);
    f(cir);

输出是什么?

int
int
int

正如 MSVC 文档所预测的那样, auto 也会发生同样的事情:)

如果您想玩的话,这是代码。


这也是 MS 网站上的示例(如果有一天它消失了)

// cl.exe /analyze /EHsc /W4
#include <iostream>

using namespace std;

int main( )
{
    int count = 10;
    int& countRef = count;
    auto myAuto = countRef;

    countRef = 11;
    cout << count << " ";

    myAuto = 12;
    cout << count << endl;
}

在前面的示例中,myAutoint,而不是 int 引用,因此输出为 11 11 code>,而不是 11 12,如果引用限定符没有被 auto

删除,情况就会如此

You can take simple answer as granted by MSVC Technical documentation:

Using auto drops references, const qualifiers, and volatile
qualifiers.

You don't need a function to achieve similar results. Consider:

int var;
const int & cref = var;
auto avar = cref;

The type of avar will be int not const int & nor int &.

To go a bit deeper into this we can go to cppreference.com and refer to template argument deduction analogy.

For example, given const auto& i = expr;, the type of i is exactly the type of the argument u in an imaginary template template<class U> void f(const U& u).

We tend to intuitively use templates and until it works we never really bother about template argument deduction rules. These rules are in fact quite complex. But we can make the "imaginary template for auto" non-imaginary and test what would have happened if we provided auto i = expr; to the template. In our case the template may look like this:

template<class U> 
void f(U u)
{
    cout << type_name<decltype(u)>() << "\n";
}

Let's feed it with variables with types of our interest:

    int i = 0;
    int & ir = i;
    const int & cir = i;
    f(i);
    f(ir);
    f(cir);

And the what's at the output?

int
int
int

The same thing would have happened with auto as predicted by MSVC docs :)

Here's the code if you wanted to play.


Here's also example from MS website if it disappeared one day

// cl.exe /analyze /EHsc /W4
#include <iostream>

using namespace std;

int main( )
{
    int count = 10;
    int& countRef = count;
    auto myAuto = countRef;

    countRef = 11;
    cout << count << " ";

    myAuto = 12;
    cout << count << endl;
}

In the previous example, myAuto is an int, not an int reference, so the output is 11 11, not 11 12 as would be the case if the reference qualifier hadn't been dropped by auto

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文