什么时候需要在C ++中使用decltype

时间:2017-03-24 18:36:15

标签: c++

我正在学习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。我想我在这里缺少一些导入概念,任何反馈都会非常有用。谢谢!

5 个答案:

答案 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

我能想到以下几点。

当您希望编译器从以下内容推导出类型时:

  1. 另一个对象的类型。
  2. 函数的返回类型。
  3. 您也可以使用:

    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相乘,导致一些中间类型类推迟实际计算,直到很久以后。