我遇到了一个有趣的问题,我不明白发生了什么:
/* 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 */
据我所知,我提供的单个整数参数可以解释为使用参数size_typecount
调用构造函数,也可以解释为使用初始化列表的构造函数。似乎只有当我提供左值时才调用initialiser_list构造函数,但当我提供r-valueint
(至少是文字)时,size_tcount
构造函数。为什么会这样?
这也意味着:
int num_elements = 6;
std::vector<int> myvector{num_elements};
结果仅为大小为1的向量;
std::vector<int> myvector(num_elements);
结果是一个大小为num\u元素的向量,但我认为应该避免这种初始化,因为偶尔会遇到最麻烦的解析问题。
让我们逐案看看发生了什么,以及为什么在使用左值时会出现上述缩小转换错误/警告。
在这里我们考虑:
int lvalue = 6; // lvalue is not a constant expression
//---------------------------v------------------->constant expression so works fine
std::vector<int*> myvector { 6 };
std::vector<int*> myvector{ lvalue };
//--------------------------^^^^^^--------------->not a constant expression so doesn't work
首先请注意,std::vector
因此,在这种情况下,将使用size\u t count
ctor。现在,让我们看看缩小转换错误/警告的原因。
当使用名为lvalue
的变量而不是使用prvalueint
时,我们得到错误/警告的原因是,在前一种情况下,lvalue不是一个常量表达式,因此我们有一个缩小的转换。这可以从dcl中看到。初始化。列表#7说明:
缩小转换是隐式转换
(重点矿山)
这意味着,从类型为int的左值(这是一个左值表达式)到向量的std::vector::vector(size\u t,/*其他参数*/)的size\u t参数的转换是缩小转换。但是从prvalue int到向量的std::vector::vector(size\u t,/*其他参数*/)参数的转换不是缩小转换。
为了证明确实如此,让我们看一些例子:
int main()
{
//----------------v---->no warning as constant expression
std::size_t a{1};
int i = 1;
//----------------v---->warning here i is not a constant expression
std::size_t b{i};
constexpr int j = 1;
//----------------v---->no warning here as j is a constexpr expression
std::size_t c{j};
return 0;
}
struct Custom
{
Custom(std::size_t)
{
}
};
int main()
{
//-----------v---->constant expression
Custom c{3}; //no warning/error here as there is no narrowing conversion
int i = 3; //not a constant expressoion
//-----------v---->not a constant expression and so we get warning/error
Custom d{i}; //warning here of narrowing conversion here
constexpr int j = 3; //constant expression
//-----------v------>no warning here as j is a constant expression and so there is no narrowing conversion
Custom e{j};
return 0;
}
演示
因此,该问题并不特定/限于std::vector,而是上述标准中引用的规则的结果。
在这里我们考虑:
std::vector<int> myvector{num_elements};//this uses constructor initializer list ctor
在这种情况下,有一个构造函数初始值设定项list ctor可用于std::vector
另一方面,当我们使用:
std::vector<int> myvector(num_elements); //this uses size_t ctor
这里,将使用std::vector的大小向量,因为在这种情况下,初始值设定项列表向量甚至不可行,因为我们使用了括号。因此将创建一个大小为6的向量。您可以使用以下示例来确认这一点:
struct Custom
{
Custom(std::size_t)
{
std::cout<<"size t"<<std::endl;
}
Custom(std::initializer_list<int>)
{
std::cout<<"initializer_list ctor"<<std::endl;
}
};
int main()
{
Custom c(3);//uses size_t ctor, as the initializer_list ctor is not viable
return 0;
}
今天我遇到了一个有趣的问题,是我自己打错的。我创建了一个lambda,它接受了对结构的引用,并错误地将其设置为按值接收参数的std::函数。 这里有一个更简洁的版本: 使用godbolt检查显示,使用MSVC编译成功,但对于Clang和GCC都失败了。 这是MSVC编译器中的bug吗?
我想存储一组/值,但是s不一定是增量的,这意味着数据可以是: 因此,我试图创建一个c#等价的
以下节目 使用当前Clang(12.0.0)编译,但不使用当前GCC(11.0.0 20201028)。使用GCC它会产生错误 根据[dcl.init.list/5]和string_view(char const*)构造函数是constepr这一事实,我假设Clang的行为就在这里。 对吗?
为什么x没有在下面初始化? 平均而言,对于一半的迭代,for循环中的将是,从而初始化。对于另一半,找到的 循环替换为 同样糟糕。只有
根据此堆栈溢出问题的公认(且唯一)答案, 使用 将改为零初始化对象。 那么,为什么呢?, 生成此输出: 定义的两个构造函数都是默认的?正当对于POD类型,默认初始化为零初始化。 根据这个问题的公认答案, 如果POD成员未在构造函数中初始化,也未在类初始化中通过C11初始化,则默认为已初始化。 不管是堆栈还是堆,答案都是一样的。 在C 98中(而不是之后),new int()被指定为执行零初始化。
问题内容: 在调试器中,这些显示为。 如何避免这种情况? 问题答案: 这些精度问题归因于浮点数的内部表示,您无法做很多事情来避免它。 顺便说一句,至少在使用现代C ++编译器时,在运行时打印这些值通常仍会导致正确的结果。对于大多数操作而言,这并不是什么大问题。