auto型别推导

前置文章 型别推导

采用auto进行变量声明时候,型别饰词取代ParamType。所以也存在三种情况:

  1. 情况1:型别饰词是指针或者引用,但不是万能引用。
  2. 情况2:型别饰词是万能引用。
  3. 情况3:型别饰词不是指针也不是引用。
int x = 27;
const int cx = x;
auto&&  uref1 = x; // x 型别为int,且为左值
                   // 所以 uref1的型别是int&
auto&& uref2 = cx; // cx 是const int,且左值, 所以 uref2是const int&
// 结论情况2时,如果是auto万能引用,且那个是左值时,都推导为左值引用

auto&& uref3 = 27; // 27型别为右值, 所以uref3的型别为int&&

同样的数组实参和函数实参的退化在非引用型别饰词的退化成指针的情况也同样适用于auto型别推导。

const char ch[] = "Hello World!"; // ch的型别是const char[13] 也就是 const T (&)[N]型别。
auto ch1 = ch; // ch1的型别是 const char*
auto ch2 = ch; // ch2的型别是 const char (&)[13]
void someFunc(int, double); // someFunc是一个函数,型别是 void(int, double)
auto func1 = someFunc; // func1的型别是void (*)(int, double)
auto func2 = someFunc; // func2的型别是void (&)(int, double)

auto型别推导和模板型别推导运作相似,只有一处不同。

int x1 = 27; // 型别int, 值为27
int x2(27); // 型别int, 值为27
int x3 = {27}; // 型别int, 值为27
int x4{27}; // 型别int, 值为27

上面都是得到一个值为27的int,但是如果把上述的int换成auto就会有点不一样

auto x1 = 27; // 型别int, 值为27
auto x2(27); // 型别int, 值为27
auto x3 = {27};// 型别std::initializer_list<int>, 值为27
auto x4{27};// 型别std::initializer_list<int>, 值为27

结论

如果用auto声明变量的初始化表达式是使用{ },那么所得的型别就是std::initalizer_list 。
但是如果 {}内的型别是不一样的,者代码编译不通过。

auto x5 = {1, 2, 3.0 }; //编译错误

auto与模板型别推导区别在于,auto会假定大括号的初始化表达式代表一个std::initializer_list,但是模板推导不会。

auto x = {1, 2, 3}; // x的型别是std::initializer_list<int>
template<typename T>
void f(T param);
f({11, 23, 9}); // 错误,无法推导T的型别

但是如果指定模板中的param为std::initilaizer_list 就可以推导T的型别

template <typename T>
void f(std::initilaizer_list<T> param);
f({1, 2, 3}); // T为int

结论:只有必要的时候才会初始化表达式时使用大括号。

在lambda表达式中看是包含auto可以进行推导,实际上是模板推导的情况。

模板推导就不会推导带{}初始化变量的情况。

auto createInitList() {
 return {1, 2, 3}; // 错误: 无法进行模板推导
}
std:: vector<int > v;
auto resetV = [&v](const auto& newValue){ v = newValue; };
resetV({1, 2, 3}); //错误, 无法为{1, 2, 3}进行型别推导。
要点
  1. 一般情况下auto型别推导和模板型别推导是一样的。但是在使用auto型别推导时会假定大括号括起来的初始化表达式为一个std::initializer_list
    而模板推导不会这样做。
  2. 在函数返回或者lambda式的形参使用auto,意思是模板型别推导,而不是auto型别推导。
资源下载链接为: https://pan.quark.cn/s/f989b9092fc5 今天给大家分享一个关于C#自定义字符串替换方法的实例,希望能对大家有所帮助。具体介绍如下: 之前我遇到了一个算法题,题目要求将一个字符串中的某些片段替换为指定的新字符串片段。例如,对于源字符串“abcdeabcdfbcdefg”,需要将其中的“cde”替换为“12345”,最终得到的结果字符串是“ab12345abcdfb12345fg”,即从“abcdeabcdfbcdefg”变为“ab12345abcdfb12345fg”。 经过分析,我发现不能直接使用C#自带的string.Replace方法来实现这个功能。于是,我决定自定义一个方法来完成这个任务。这个方法的参数包括:原始字符串originalString、需要被替换的字符串片段strToBeReplaced以及用于替换的新字符串片段newString。 在实现过程中,我首先遍历原始字符串,查找需要被替换的字符串片段strToBeReplaced出现的位置。找到后,就将其替换为新字符串片段newString。需要注意的是,在替换过程中,要确保替换操作不会影响后续的查找和替换,避免遗漏或重复替换的情况发生。 以下是实现代码的大概逻辑: 初始化一个空的字符串result,用于存储最终替换后的结果。 使用IndexOf方法在原始字符串中查找strToBeReplaced的位置。 如果找到了,就将originalString中从开头到strToBeReplaced出现位置之前的部分,以及newString拼接到result中,然后将originalString的查找范围更新为strToBeReplaced之后的部分。 如果没有找到,就直接将剩余的originalString拼接到result中。 重复上述步骤,直到originalStr
### C++ 中 `auto` 关键字的含义与用法 #### 一、基本概念 `auto` 是一种类说明符,最早引入于 C++11 标准中。它的主要作用是在声明变量时让编译器自动推导该变量的实际类[^1]。 #### 二、具体行为分析 ##### (一)通用引用类推导 当使用 `auto&&` 进行变量声明时,它可以既作为左值引用也可以作为右值引用工作。这意味着通过这种方式能够灵活处理不同种类的对象实例化需求。 ```cpp #include <type_traits> using namespace std; int main() { int i = 1; auto&& x{i}; auto&& y{2}; cout << is_same_v<int&, decltype(x)> << endl; // 输出:1 (true) cout << is_same_v<int&&, decltype(y)> << endl; // 输出:1 (true) } ``` 这里展示了对于已命名对象 `i` ,其会被视为左值从而绑定到左值引用;而对于临时量 `{2}` 则自然成为右值并因此关联至右值引用之上[^1]。 ##### (二)针对数组类的特殊表现形式 如果初始化表达式为数组,则即便采用 `auto` 来定义新实体,最终得到的结果却是指向首元素的一个指针而非真正的数组副本本身。 ```cpp #include <iostream> #include <typeinfo> using namespace std; int main(){ int a3[3] = {1, 2, 3}; auto b3 = a3; cout << typeid(b3).name() << endl; // 可能打印类似于 "Pi" 的字符串,表示这是一个指向整数的指针 } ``` 此现象提醒开发者注意,在某些场景下单纯依赖默认机制可能导致意外后果,需额外小心对待[^2]。 ##### (三)关于常量修饰的影响 值得注意的是,当源数据带有 `const` 属性时,除非特别指定否则目标变量不会继承这一特性。也就是说,即使原始资料不可变,经由 `auto` 得来的拷贝依旧允许修改操作。 ```cpp void func1() { const int constcount = 10; auto myAuto2 = constcount; try{ myAuto2 = 30; // 编译可以通过,因为myAuto2并非const } catch(...){ } cout << "constcount: "<< constcount<<endl; // 输出仍保持原样不变 cout << "myAuto2: "<< myAuto2<<endl; // 而这里是更新后的数值 } ``` 上述例子表明虽然 `constcount` 不可更改,但基于它创建出来的 `myAuto2` 却不受相同约束限制[^4]。 #### 三、最佳实践建议 为了避免潜在陷阱,《Effective Modern C++》提倡利用显示类初始化方法来增强代码意图透明度以及减少误判风险。“隐形”的代理别确实容易引发误解,所以应当尽量避免完全依靠隐式的类推测流程[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值