如何让c ++ 11自动更聪明?

时间:2017-06-15 07:58:08

标签: c++ c++11

我现在开始在c ++ 11中使用auto关键字。我发现它不那么聪明的一件事在下面的代码中说明:

unsigned int a = 7;
unsigned int b = 23;
auto c = a - b;
std::cout << c << std::endl;

如您所见,c变量的类型是unsigned int。但我的意图是两个unsigned int的区别应该是int。所以我希望变量c等于-16。我怎样才能更明智地使用auto,以便它可以将c变量的类型推断为int?谢谢。

3 个答案:

答案 0 :(得分:6)

ab都有 unsigned int 的类型。因此,表达式a - b的类型推断为 unsigned int c的类型为 unsigned int 。所以 auto 就像它应该的那样工作。

如果要将类型从 unsigned int 更改为 int ,可以使用 static_cast

auto c = static_cast<int>(a - b);

或明确指定c的类型:

int c = a - b;

答案 1 :(得分:1)

你误解了unsigned int类型是什么。

unsigned int是一个mod - 2^k,用于某些k(通常为32)整数。减去两个这样的mod - 2^k整数是明确定义的,并且不是有符号整数。

如果您想要一种模型从-2^k2^k-1(k通常等于31)的有界整数集的模型,请使用int代替unsigned int。如果你想让他们变得积极,那就让他们变得积极。

尽管名称如此,unsigned int不是int,但没有任何迹象,因此是正面的。相反,它是一种非常具体的整体类型,恰好没有符号概念。

如果你不需要mod-2^k数学用于某个未知的实现定义k,并且并不是绝对不能将每个数量级的数据包打包成值,请不要使用unsigned int

您想要的是

positive<int> a = 7;
positive<int> b = 23;
auto c = a-b; // c is of type `int`, because the difference of two positive values may be negative

通过一些语法更改和可能的大量工作,但它不是unsigned的含义。

答案 2 :(得分:1)

因为不知道基本表达式是如何工作的,所以C ++ 11 auto关键字是愚蠢的吗?这怎么对你有意义?

在表达式auto c = a - b;中,auto c =与子表达式a - b中使用的类型无关。

自从第一个C语言草稿以来,表达式使用的类型由该表达式的操作数决定。对于从预标准K&amp; R C到C ++ 17的所有内容都是如此。

现在,如果你想要负数,你需要做的就是使用负面类型,这并不奇怪。在调用int运算符之前,将操作数更改为(signed)-或将它们转换为该类型。

将结果声明为有符号类型而不更改-操作数的类型并不是一个好主意,因为这会强制从无符号转换为有符号,这不一定是明确定义的行为。

现在,如果操作数具有不同的类型,或者是小整数类型,则它们将按照通常的算术转换进行隐式提升。这不适用于这种特定情况,因为两个操作数是相同类型而不是小整数类型。

但是...... 这个auto关键字愚蠢和危险的原因。考虑:

unsigned short a = 7;
unsigned short b = 23;
auto c = a - b;

由于两个操作数都是无符号的,程序员打算使用无符号算术。但是这里两个操作数都被隐式提升为int,意外改变了签名。 auto关键字假装没有发生任何事情,而unsigned int c = a - b;会增加编译器诊断消息的机会,或者至少增加外部静态分析工具发出警告的可能性。而且它也会意外地平滑掉原本可能会发生变更的错误。

此外,对于auto,我们最终会为声明的变量设置错误的,无意的类型。