const auto & 和 auto & 之间的区别,如果引用对象是 const

Difference between const auto & and auto & if object of reference is const

// case 1
const int i = 42;
const auto &k = i;

// case 2
const int i = 42;
auto &k = i;

在这种情况下,auto 之前是否需要 const 关键字?毕竟,对自动推导类型的引用 (k) 将包含对象的顶层 const (constint i)。所以我相信 k 将是对在这两种情况下都是常数 (const int &k) 的整数的引用。

如果这是真的,那是否意味着情况 1 中的 const auto &k = i; 被编译器替换为 const int &k = i;auto 被替换为 int)?而在情况 2 中,auto 被替换为 const int?

在第一种情况下略有不同 auto 将推导为 const int,在第二种情况下将推导为 int(正如您明确说明的 const)。

cpp-reference states

The keyword auto may be accompanied by modifiers, such as const or &, which will participate in the type deduction. For example, given const auto& i = expr;, the type of i is exactly the type of the argument u in an imaginary template template void f(const U& u) if the function call f(expr) was compiled. Therefore, auto&& may be deduced either as an lvalue reference or rvalue reference according to the initializer, which is used in range-based for loop.

所以对你来说这意味着

// case 1
const int i = 42;   
const auto &k = i;   // auto -> int

// case 2
const int i = 42;
auto &k = i;  // auto -> const int

但是,在我看来,更重要的是,如果您明确声明 const 并保证常量,则意图会更清楚。因此,在这种情况下,我显然更喜欢它。

auto关键字在编译时自动决定变量的类型。

在第一种情况下,auto 减少为 int,在第二种情况下减少为 const int。因此,您的两种情况都减少为与以下代码相同的代码:

const int &k = i;

但是,为了更好的可读性并确保您的变量 TRULYconst.

,最好显式地使用 const

使用 auto 的类型推导类似于模板参数类型推导,但有一些不适用于给定示例的例外情况。因此

const int i = 42;
const auto& k1 = i; // same as const int& k1 = i;
auto& k2 = i; // same as (const int)& k2 = i;

尽管如此,添加 const 限定符可能更具可读性。

这是另一个例子,其中 auto 的简洁性具有误导性:

int *i;
const auto k1 = i; // same as int* const k1 = i;
const auto *k2 = i;  // same as const int *k2 = i;

第一种情况i指向的对象可以通过k1修改,第二种情况不可以

接受的答案是正确的,即编译结果没有区别。需要注意的重要一点是 auto& 版本是 耦合 const 参考 kconst-变量的内在性 i。我想既然问题的标题是“const auto & 和 auto & ... 之间的区别”,那么强调这里的实用差异很重要,如果你不把const 关键字,你不能保证引用会有这个 cv-qualification。在某些需要这样做的情况下,为什么要让 i 有机会在未来保持 const

您好,欢迎来到 stack overflow。

正如这个小测试程序所示,无论您如何指定 k 的类型,编译器都不会让您丢失 i.

的常量
#include <iostream>
#include <type_traits>
#include <string>

#define XSTR(s) STR(s)
#define STR(s) #s

template<class T> 
struct type;

template<>
struct type<int>
{
    static std::string name() { return "int"; }
};

template<class T>
struct type<T&&>
{
    static std::string name() { return type<T>::name() + " &&"; }
};

template<class T>
struct type<T&>
{
    static std::string name() { return type<T>::name() + " &"; }
};

template<class T>
struct type<T const>
{
    static std::string name() { return type<T>::name() + " const"; }
};

#define REPORT_CONST(decl, var, assign) \
{ \
    decl var = assign; \
    do_it(STR(decl var = assign;), var); \
}

template<class Var> 
void do_it(const char* message, Var&&)
{
    std::cout << "case: " << message << " results in type: " << type<Var>::name() << '\n';
}

int main()
{
    const int i = 42;

    REPORT_CONST(const auto &, k, i);
    REPORT_CONST(auto &, k, i);
    REPORT_CONST(auto &&, k, std::move(i));
    REPORT_CONST(auto const &&, k, std::move(i));
    REPORT_CONST(int const&, k, i);
    // REPORT_CONST(int &, k, i); // error: binding reference of type 'int&' to 'const int' discards qualifiers
}

预期结果:

case: const auto & k = i; results in type: int const &
case: auto & k = i; results in type: int const &
case: auto && k = std::move(i); results in type: int const &
case: auto const && k = std::move(i); results in type: int const &
case: int const& k = i; results in type: int const &

http://coliru.stacked-crooked.com/a/7c72c8ebcf42c351

另请注意命名的 r 值到 l 值的衰减。