类型推断“自动”和按引用调用如何工作?

时间:2018-09-29 20:02:50

标签: c++ string pointers

&c如何在此循环以及分配c = toupper(c)的过程中工作?

string str = "hello";

for (auto & c: str)
  c = toupper(c);

你能解释一下吗?

2 个答案:

答案 0 :(得分:1)

首先,请注意,如果std::toupper的值为EOF以外的其他值,则它具有未定义的行为。对于大多数编译器,char默认为带符号类型。在典型的8位字节计算机上,这意味着如果c的值不在ASCII范围内(从0到127),则它为负数,则得到UB。

解决该问题的一种简单方法是将参数强制转换为unsigned char

auto to_upper( const char c )
    -> char
{
    using Byte = unsigned char;
    return static_cast<char>( toupper( static_cast<Byte>( c ) );
}

仍然,此功能默认情况下仅适用于ASCII字符,即字母A到Z,因为它采用C级语言环境指定的编码,默认情况下为"C",本质上仅限于ASCII。但至少可以避免未定义行为。因此,让我们假设您的示例使用了它,

for( auto& c : str ) c = to_upper( c );

这是基于范围的for循环,它遍历str中的所有项目,将引用c绑定到每个项目并执行循环主体具有这种约束力。由于str的项目类型为char,因此auto将推论为char。因此,与编写for( char& c : str ) ...相同。

因此,默认情况下,它会将str中的所有ASCII字符都大写。

在Windows中,如果已经通过setlocale( LC_ALL, "" )设置了C语言环境,则假定的编码将为Windows ANSI,并且如果str包含编码为to_upper的字符,将执行其大写操作正确地。这意味着在Windows中可以将其用于例如大写挪威语字符串,例如"Blåbærsyltetøy",前提是Windows的语言环境是使用Windows ANSI Western的语言环境。

在* nix中,调用setlocale无济于事,因为用户的本机语言环境将指定UTF-8编码,其中ASCII以外的每个字符都表示为两个或多个字节,大于127。

答案 1 :(得分:0)

auto & c等效于char & c,它是对字符串中每个字符的引用。更新引用的值会更改字符串中的引用字符。

上面的代码的结果将是一个大写的字符串。