标签: list-initialization

为什么列表初始化允许从double转换为float值?

列表初始化({...}语法)不允许缩小转换.例如,尝试列表初始化一个int iwith会3.14f产生编译错误,因为从浮点值到整数的转换正在缩小:

<source>:11:32: error: narrowing conversion of '3.1400001e+0f' from 'float' to 'int' inside { } [-Wnarrowing]
     int i{3.14f};
                ^
Run Code Online (Sandbox Code Playgroud)

随着中说,为什么它可以构造一个float f3.14,这是类型的double?(从转换doublefloat被认为是缩小的.)执行以下操作:

float f{3.14};
Run Code Online (Sandbox Code Playgroud)

不保留编译错误.

c++ c++11 list-initialization

11
推荐指数
1
解决办法
364
查看次数

MSVC大括号初始化与双打似乎违反了标准?

看看这个简单的程序:

int main() {
    float f2 = 7.2; // OK, with warning
    float f3 = 7.199999809265137; // OK, no warning
    float f4{ 7.2 }; // Fails
    float f5{ 7.199999809265137 }; // OK, no warning
    float f6 = { 7.2 }; // Fails
    float f7 = { 7.199999809265137 }; // OK, no warning
}
Run Code Online (Sandbox Code Playgroud)

使用默认选项(cl /W4版本19.00.23918)使用MSVC 2015编译时,我收到以下消息:

FloatTest.cpp(2): warning C4305: 'initializing': truncation from 'double' to 'float'
FloatTest.cpp(4): error C2397: conversion from 'double' to 'float' requires a narrowing conversion
FloatTest.cpp(4): …
Run Code Online (Sandbox Code Playgroud)

c++ visual-c++ language-lawyer c++11 list-initialization

10
推荐指数
1
解决办法
291
查看次数

为什么直接列表初始化会导致类型引用转换的歧义,如果声明了对类型的引用运算符和对类型的引用?

这个答案的背景下,问题就出现了.

考虑一个例子:

struct foo {
    int value;
    operator int&(){ return value; }
    operator int(){ return value; }
};

int main () {
    int &a(foo{}); // #1
    //int &b{foo{}}; // #2 -- ambiguity
    int &c = foo{}; // #3
    //int &d = {foo{}}; // #4-- ambiguity
    int &d { a }; // #5
    int &e = { a }; // #6
    (void)a;
    (void)c;
    (void)d;
    (void)e;
}
Run Code Online (Sandbox Code Playgroud)

我不明白为什么#2和#4引起歧义,而#1和#3则不然.所以问题是 - 为什么直接列表初始化会导致隐式强制转换引用的歧义,如果声明类型和对类型的引用的转换运算符?

c++ ambiguity typecast-operator list-initialization

10
推荐指数
1
解决办法
128
查看次数

C++ 11空列表联合的初始化 - 是否保证初始化联合的全长?

在C++ 11中,我有以下联合:

union SomeData
{
    std::uint8_t Byte;
    std::uint16_t Word;
    std::uint32_t DWord;
    unsigned char String[128];
};
Run Code Online (Sandbox Code Playgroud)

如果我这样初始化联盟;

SomeData data {};
Run Code Online (Sandbox Code Playgroud)

是否保证联盟的全部内容都将"归零"?换一种方式; 是一个联合的空列表初始化程序,在功能上等同于将联合设置为零?:

memset(&data, 0, sizeof(data));
Run Code Online (Sandbox Code Playgroud)

特别是,我关心字符串数据.我想确保字符串的整个长度包含零.它似乎在我当前的编译器中工作,但规范的语言是否保证这始终是真的?

如果不是:有没有更好的方法将联合的全长初始化为零?

c++ unions c++11 list-initialization

10
推荐指数
2
解决办法
736
查看次数

显式构造函数和嵌套初始化列表

以下代码成功编译了大多数现代C++ 11兼容编译器(GCC> = 5.x,Clang,ICC,MSVC).

#include <string>

struct A
{
        explicit A(const char *) {}
        A(std::string) {}
};

struct B
{
        B(A) {}
        B(B &) = delete;
};

int main( void )
{
        B b1({{{"test"}}});
}
Run Code Online (Sandbox Code Playgroud)

但是为什么它首先编译,以及列出的编译器如何解释该代码?

为什么MSVC能够在没有的情况下编译它B(B &) = delete;,但其他3个编译器都需要它?

为什么在删除复制构造函数的不同签名时,除了MSVC之外的所有编译器都会失败,例如B(const B &) = delete;

编译器甚至都选择相同的构造函数吗?

为什么Clang会发出以下警告?

17 : <source>:17:16: warning: braces around scalar initializer [-Wbraced-scalar-init]
        B b1({{{"test"}}});
Run Code Online (Sandbox Code Playgroud)

c++ overload-resolution c++11 list-initialization

10
推荐指数
1
解决办法
1130
查看次数

复制列表初始化是否在概念上调用复制ctor?

在C++ 11之前,我们可以通过编写类似于A a = 1;或多或少相当的东西来进行复制初始化A a = A(1);.也就是说,首先创建临时,然后调用复制ctor.无论版本是否复制,这必须是概念上的,并且必须可以访问复制文件.

使用C++ 11中的列表初始化,我们可以通过写入来进行复制列表初始化A a = {1, 2};.在我看来,这应该或多或少相当于A a = A(1, 2);.但是,在GCC和clang上,A a = {1, 2}即使复制和移动ctor不可访问(通过声明为私有)也会编译.但是,A a = 1;如果相应的复制/移动ctor不可访问,则不会在GCC或clang上编译.所以,A a = {1, 2};似乎或多或少等同于A a{1, 2};直接列表初始化.这与实际直接列表初始化之间的区别在于,A a = {1, 2};如果采用两个整数的ctor是显式的,则不会编译.在这方面,A a = {1, 2};类似于复制初始化.

所以,我的问题是:A a = {1, 2};概念上表达式的确切语义是什么?从概念上讲,复制省略不会妨碍.

c++ copy-constructor copy-initialization c++11 list-initialization

9
推荐指数
1
解决办法
406
查看次数

如果大括号括号列表是类构造函数的大小,则编译时错误

我正在尝试编写一个基于数学向量的类:

template <unsigned N> class Vector{
public:
    Vector() = default;
    Vector(std::initializer_list<double> li) { *this = li;}
    Vector& operator=(std::initializer_list<double>);

private:
    std::array<double, N> x = {}
}

template <unsigned N> inline Vector<N>& Vector<N>::operator=(std::initializer_list<double> li){
     if(N != li.size()) throw std::length_error("Attempt to initialise Vector with an initializer_list of different size.");
     std::copy(li.begin(), li.end(), x.begin());
     return *this;
}
Run Code Online (Sandbox Code Playgroud)

我希望能够编写这样的代码;

Vector<3> a = {1,2,3};
a = {3,5,1};
Run Code Online (Sandbox Code Playgroud)

用户期望编写这样的代码是很自然的,对吧?但是,如果我使用错误大小的初始化列表,我希望发生编译时错误std::array.

 std::array<double, 3> a = {2,4,2,4} //compile time error
 Vector<3> a = {3,5,1,5} //run-time error as …
Run Code Online (Sandbox Code Playgroud)

c++ templates c++11 list-initialization

9
推荐指数
2
解决办法
373
查看次数

支撑初始化与括号错误

我正在为此提交GCC错误,但我宁愿仔细检查一下.

考虑以下程序:

#include <utility>
template<typename T, typename A>
void F(A&& a) { T(std::forward<A>(a)); } // Note: () syntax.
int main() { int i; F<int&>(i); }
Run Code Online (Sandbox Code Playgroud)

和:

#include <utility>
template<typename T, typename A>
void F(A&& a) { T{std::forward<A>(a)}; } // Note: {} syntax.
int main() { int i; F<int&>(i); }
Run Code Online (Sandbox Code Playgroud)

最新的Clang和MSVC编译器都接受这两个程序.GCC 5及以后接受第一个程序,但拒绝第二个程序,声称invalid cast of an rvalue expression of type 'int' to type 'int&'.

这是GCC的错误吗?还是这的确之间的差异T{},并T()在上述背景下(因此臭虫锵和MSVC)?

编辑:

问题可以缩小到以下简单的摘录:

int i; (int&){i};
Run Code Online (Sandbox Code Playgroud)

int i; (int&)(i);
Run Code Online (Sandbox Code Playgroud)

c++ gcc c++11 list-initialization

9
推荐指数
1
解决办法
264
查看次数

直接初始化与直接列表初始化(C++)

DIRECT-VS COPY-INITIALIZATION
通过这个问题(它是直接初始化还是复制初始化?)我学到了直接初始化复制初始化之间的区别:

direct-initialization                   copy-initialization
-----------------------                 ---------------------

obj s("value");                         obj s = obj("value");
                                        obj s = "value";

obj s{"value"};                         obj s = {"value"};
                                        obj s = obj{"value"};
Run Code Online (Sandbox Code Playgroud)

为了完整起见,我在这里提到它.我对此页面的实际问题列在下一段>>

 
直接初始化与直接列表初始化
答案显示,在直接初始化的范畴内,可以在直接初始化直接列表初始化之间产生差异.

obj s("value");   // direct-initialization

obj s{"value"};   // direct-list-initialization
Run Code Online (Sandbox Code Playgroud)

我知道列表初始化不允许缩小,这样初始化int x{3.5};就不会编译.但除此之外,我还有几个问题:

 
(1)
obj s("value");和之间的编译器输出有什么不同obj s{"value"};吗?
让我们考虑一个没有任何优化的编译器.我想知道任何可能的技术差异:-)

 
(2)也许我应该问一个多变量初始化完全相同的问题,例如:
obj s("val1", "val2");obj s{"val1", "val2"};

 
(3)我注意到列表初始化有时可以调用不同的构造函数,如:

vector<int> a{10,20};   //Curly braces -> fills the …
Run Code Online (Sandbox Code Playgroud)

c++ list-initialization c++17

9
推荐指数
2
解决办法
1386
查看次数

列表初始化 - C++14 有什么变化?

在此处输入图片说明这两行来自cppreference

这两种说法有什么区别?我看不出任何区别

直到 C++14

如果花括号初始化列表为空并且 T 是具有默认构造函数的类类型,则执行值初始化。否则,如果 T 是聚合类型,则执行聚合初始化。

从 C++14 开始

如果 T 是聚合类型,则执行聚合初始化。否则,如果花括号初始化列表为空并且 T 是具有默认构造函数的类类型,则执行值初始化。

c++ language-lawyer list-initialization

9
推荐指数
1
解决办法
151
查看次数