我正在学习C ++,并在C ++入门中找到了以下代码:
int main() {
string s("some string");
for(decltype(s.size()) index = 0; index != s.size() && !isspace(s[index]); ++index)
s[index] = toupper(s[index]);
cout << s;
}
我理解代码将字符串中的第一个单词大写,输出为
SOME string
我很好奇的是,为什么你需要使用decltype(s.size())
来声明索引的类型。如果我将其更改为int index =0
,代码仍然可以编译并运行,没有任何问题。我似乎更容易使用int
。我想我在这里缺少一些导入概念,任何反馈都会非常有用。谢谢!
答案 0 :(得分:7)
您 或者至少它不适合进入。
decltype(s.size())
字面意思是&#34;此类型应与int
用于存储字符串长度的任何类型相同&#34;。在大多数C ++实现中,这是decltype(s.size())
,它将是无符号的64位整数(在大多数情况下)或无符号的32位整数。在任何一种情况下,std::string
(已签名且可能不会是64位)都不会代表size_t
个对象的整个可能的大小范围,在异国情况下,超过21亿个字符。在这些情况下,如果您将类型定义为int
,则存在未定义行为的风险。
请注意,在我的代码中,我经常只写std::string
,因为它更简单。但是如果你想保证代码在所有平台上运行,int
是最安全的代码版本。
答案 1 :(得分:3)
他们使用decltype(s.size())
代替int
的共鸣是因为使用int
可能会导致溢出,这是未定义的行为。 std::string::size()
返回一个无符号整数类型,可以存储您可以创建的最大大小的字符串。如果int
无法保存该值且字符串为该大小,那么尝试运行int
到该值将无法正常工作
在C ++ 11之前,您必须使用std::string::size_type
,如果您更改了类型,则必须更改std::string
部分。现在我们已经拥有C ++ 11及更高版本,我们不再需要这样做了。编译器知道事物的类型是什么,如果我们使用decltype(s.size())
我们得到正确的类型,如果我们改变s
,那么for循环中什么都不需要改变。从可维护性的角度来看,这非常好。
答案 2 :(得分:1)
何时需要在C ++中使用decltype
我能想到以下几点。
当您希望编译器从以下内容推导出类型时:
您也可以使用:
auto size = s.size();
for(decltype(size) index = 0; index != size && !isspace(s[index]); ++index)
s[index] = toupper(s[index]);
答案 3 :(得分:1)
原因是
字符串类的s.size()
成员函数的类型是string::size_type
,它是无符号的并且可以
保持任何长度的字符串。
在这段代码中,index
是一个随循环运行而增加的变量
直到它的值等于s.size()-1
。
字符串的长度可以是任意大小。所以我们不能使用int
来表示更长的字符串
可以保存仅特定范围的值。因此,如果字符串的大小index
可以保存该值
任何大小没有显示任何错误。
答案 4 :(得分:1)
嗯,decltype更有用的地方是:
template<class T1, class T2>
auto mul(T1 a, T2 b) -> decltype(a*b){
return a*b;
}
这个模板允许你将两个东西相乘,可能是不同类型的东西,并且会返回一些正确类型的结果,将两者相乘。一个假设的例子可能是将两个matricies相乘,导致一些中间类型类推迟实际计算,直到很久以后。