我是C++初学者,我正在阅读Bjarne Stroustrup的编程:使用C++的原理和实践.
在3.9.2"不安全转换 "一节中,作者提到了
当初始化程序是整数文字时,编译器可以检查实际值并接受不暗示缩小的值:
Run Code Online (Sandbox Code Playgroud)int char b1 {1000}; // error: narrowing (assuming 8-bit chars)
我对这个宣言感到困惑.它使用两种类型(int和char).我以前从未在Java和Swift中看过这样的声明(我比较熟悉的两种语言).这是拼写错误还是有效的C++语法?
c++ initialization type-conversion narrowing uniform-initialization
在以下代码中:
final int a;
a=2;
byte b=a; // error: possible loss of precision
Run Code Online (Sandbox Code Playgroud)
为什么我会收到此错误?是不是a最终变量编译时常量表达式,因此在赋值期间隐式缩小为字节?
换句话说,上面的代码不等同于:
final int a=2;
byte b=a;
Run Code Online (Sandbox Code Playgroud) 我发现narrow-to-region命令很有用,但它适用于缓冲区而不适用于当前窗口.
我想让一个窗口显示缓冲区的缩小版本,而缓冲区如果出现在任何其他窗口中则显示为加宽.
这可能吗?
我知道在 Java 中整数文字默认是int,所以如果我写这样的东西
byte byteValue = 2;
Run Code Online (Sandbox Code Playgroud)
Java 自动将文字值2(默认为 int)转换为字节。如果我写同样的事情
byte byteValue = 4/2;
Run Code Online (Sandbox Code Playgroud)
RHS 被评估为一个 int 并隐式转换为一个字节。
但是为什么在以下两种情况下不会发生隐式转换?
int n1 = 4;
byte value = n1/2;
Run Code Online (Sandbox Code Playgroud)
或在此
byte n1 = 4;
byte value = n1/2;
Run Code Online (Sandbox Code Playgroud)
我知道这两个示例的 RHS 都被评估为int。但是为什么Java不像前两种情况那样将其隐式转换为字节。是否只有在存在文字时才会隐式转换为较小的数据类型?
我遇到了一个有趣的问题,我无法理解发生了什么:
/* I WANT 6 ELEMENTS */
int lvalue = 6;
std::vector<int*> myvector { 6 }; /* WORKS FINE */
std::vector<int*> myvector{ lvalue }; /* DOESN'T WORK */
/* Element '1': conversion from 'int' to 'const unsigned __int64 requires a narrowing conversion */
Run Code Online (Sandbox Code Playgroud)
据我所知,我提供的单个整数参数可以解释为使用 argument 调用构造函数size_type count,也可以解释为采用初始值设定项列表的构造函数。似乎initialiser_list只有当我提供左值时才调用构造函数,而size_t count当我给出右值int(好吧,至少是一个文字)时才调用构造函数。为什么是这样?
这也意味着:
int num_elements = 6;
std::vector<int> myvector{num_elements};
Run Code Online (Sandbox Code Playgroud)
结果仅是大小为 的向量1;
std::vector<int> myvector(num_elements);
Run Code Online (Sandbox Code Playgroud)
结果是一个 size 的向量num_elements,但我认为应该避免这种初始化,因为偶尔会遇到最令人烦恼的解析问题。
考虑一下这段C++ 11代码:
#include <iostream>
struct X
{
X(bool arg) { std::cout << arg << '\n'; }
};
int main()
{
double d = 7.0;
X x{d};
}
Run Code Online (Sandbox Code Playgroud)
在初始化过程中,从double到bool的转换范围正在缩小x.根据我对标准的理解,这是错误的代码,我们应该看到一些诊断.
Visual C++ 2013发出错误:
error C2398: Element '1': conversion from 'double' to 'bool' requires a narrowing conversion
Run Code Online (Sandbox Code Playgroud)
但是,Clang 3.5.0和GCC 4.9.1都使用以下选项
-Wall -Wextra -std=c++11 -pedantic
Run Code Online (Sandbox Code Playgroud)
编译此代码没有错误,也没有警告.运行程序输出1(不出意外).
现在,让我们深入到陌生的领域.
改变X(bool arg)以X(int arg)和,突然间,我们从锵得到一个错误
error: type 'double' cannot be narrowed to 'int' in initializer list [-Wc++11-narrowing]
Run Code Online (Sandbox Code Playgroud)
海湾合作委员会发出警告
warning: …Run Code Online (Sandbox Code Playgroud) c++ standards-compliance narrowing c++11 list-initialization
给定一个带有单个string[]参数的函数myArray。
如果我评估该.length属性并且该属性大于 0,那么(假设我的变量没有any伪装)它不可能是myArray[0]未定义的。但是,如果我启用noUncheckedIndexedAccess,它的类型将是string | undefined
const myFunc = (myArray: string[]) => {
if(myArray.length > 0) {
const foo = myArray[0] // now typed at 'string | undefined'
}
}
Run Code Online (Sandbox Code Playgroud)
现在我可以将 if 语句更改为评估myArray[0],并undefined按照您的预期从类型中删除。但是,如果我现在想要检查数组的长度是否大于 6,该怎么办?我不想对索引 0-5 执行相同的操作来正确缩小类型范围。例如:
const myFunc = (myArray: string[]) => {
if(myArray[0] && myArray[1] && myArray[2] && myArray[3] && myArray[4] && myArray[5]) {
const foo = myArray[0] // now typed …Run Code Online (Sandbox Code Playgroud) g ++ 4.9.0 -O2 -std = c ++ 11
template<class T>
struct vec3 {
T x, y, z;
vec3() = default;
vec3(const vec3<T> &other) = default;
vec3(T xx, T yy, T zz) { x = xx; y = yy; z = zz; }
vec3<T> operator-(const vec3<T> &other) {
return vec3<T>{ x - other.x, y - other.y, z - other.z };
}
};
int main() {
vec3<char> pos{ 0, 0, 0 };
vec3<char> newPos{ 0, 0, 0 };
auto p = …Run Code Online (Sandbox Code Playgroud) 我有以下代码:
class A
{
public:
A(const unsigned int val) : value(val) {}
unsigned int value;
};
int main()
{
int val = 42;
A a(val);
A b{val}; // <--- Warning in GCC, error in Microsoft Visual Studio 2015
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为什么仅在列表初始化使用的情况下才会出现缩小转换警告?
static_cast在C++ 11/14或实现此功能的库中是否有"安全"替代方案?
"安全"我的意思是演员应该只允许不失精度的演员.因此,如果数字适合a ,则仅允许来自int64_tto int32_t的强制转换int32_t,否则报告错误.
narrowing ×10
c++ ×6
c++11 ×4
java ×2
casting ×1
constants ×1
elisp ×1
emacs ×1
expression ×1
templates ×1
type-safety ×1
typescript ×1