标签: list-initialization

什么语言规则允许C++ 11推断出这是对的initializer_list?

在C++ 11中,初始化a似乎是合法的std::map<std::string, int>,如下所示:

std::map<std::string, int> myMap = {
     { "One",   1 },
     { "Two",   2 },
     { "Three", 3 }
};
Run Code Online (Sandbox Code Playgroud)

直观地看,这是有道理的-在括号内的初始化是对串的名单,并std::map<std::string, int>::value_typestd::pair<std::string, int>(可能有一些const资质.

但是,我不确定我是否理解这里的打字工作方式.如果我们在这里消除变量声明并且只是使用大括号括起初始化器,编译器就不会知道它正在查看a,std::initializer_list<std::pair<std::string, int>>因为它不知道被支撑的对代表std::pairs.因此,似乎编译器以某种方式推迟将类型赋值给括号封闭的初始化器,直到它从std::map构造函数中获得足够的类型信息来实现嵌套大括号用于对.我不记得在C++ 03中发生过这样的事情; 据我所知,表达式的类型从不依赖于它的上下文.

哪些语言规则允许此代码正确编译,以及编译器确定用于初始化列表的类型?我希望能够获得有关C++ 11规范的具体参考的答案,因为它的确很有意义!

谢谢!

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

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

复制列表初始化是否在概念上调用复制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
查看次数

在基于范围的for循环中使用大括号的初始化程序列表是否不安全?

这与我今天早些时候提出问题非常相似。但是,我在该问题中引用的示例是不正确的。错误地,我查看的是错误的源文件,而不是实际出现我所描述的错误的文件。无论如何,这是我的问题的一个示例:

struct base { };
struct child1 : base { };
struct child2 : base { };

child1 *c1;
child2 *c2;

// Goal: iterate over a few derived class pointers using a range-based for loop.
// initializer_lists are convenient for this, but we can't just use { c1, c2 }
// here because the compiler can't deduce what the type of the initializer_list
// should be. Therefore, we have to explicitly spell out that we want …
Run Code Online (Sandbox Code Playgroud)

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

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

直接初始化与直接列表初始化(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
查看次数

为什么不能用两层list-initializers初始化2D std :: array?

有人可以帮助我理解为什么我的编译器不能/不推断这个?(使用g ++ 7.3)

不起作用:

#include <array>
std::array<std::array<double,2>,2> f() {
 return {{0,0},{0,0}};
}
Run Code Online (Sandbox Code Playgroud)

工作良好:

#include <array>
std::array<std::array<double,2>,2> f() {
 return {std::array<double,2>{0,0},{0,0}};
}
Run Code Online (Sandbox Code Playgroud)

奇怪的是,这也失败了:

#include <array>
std::array<std::array<double,2>,2> f() {
 return std::array<std::array<double,2>,2>{{0,0},{0,0}};
}
Run Code Online (Sandbox Code Playgroud)

@ 1201ProgramAlarm指出添加另一组花括号有效:

#include <array>
std::array<std::array<double,2>,2> f() {
 return {{{0,0},{0,0}}};
}
Run Code Online (Sandbox Code Playgroud)

它使用聚合初始化,因为std::array没有用于brace-init-list的构造函数.那没关系,但那么为什么/如何运作?

std::array<double,2> x{1,2};
Run Code Online (Sandbox Code Playgroud)

为什么它处理这种情况但不处理嵌套的情况?

c++ list-initialization stdarray

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

使用普通ctor统一初始化派生类

我试图用c ++ 11统一初始化来解决一些极端情况,我无法弄清楚为什么会这样:

struct Base
{
    int x,y,z;
};

struct Derived : Base
{
};
static_assert (std::is_trivial<Base>::value, "Base must be trivial");
static_assert (std::is_trivial<Derived>::value, "Derived must be trivial");

Base b{1, 2, 3};           // 1) This compiles fine
Derived d{10, 20, 30};     // 2) This fails
Run Code Online (Sandbox Code Playgroud)

标记为2的行失败,并带有"无用于初始化Derived的匹配构造函数"消息clang 3.1g++ 4.7.

我无法理解为什么,在Derived的情况下,它试图调用构造函数而不执行(我不知道如何调用它,可能是聚合初始化?),就像第1行的情况一样.

以下推理中的某些内容是错误的?:

A)微不足道的保证它可以静态初始化

B)要静态初始化没有代码必须在运行时执行,因此不需要构造函数调用 A+B=>为什么它试图在一个它知道微不足道的类型上调用构造函数?

我很困惑....

c++ inheritance uniform-initialization c++11 list-initialization

8
推荐指数
1
解决办法
1307
查看次数

启用默认初始化列表构造函数

我相信现代C++初始化列表对于初始化对象非常有用,从而无需定义自己的构造函数:

struct point
{
    float coord[3];
};

point p = {1.f, 2.f, 3.f}; // nice !
Run Code Online (Sandbox Code Playgroud)

但是,当我的类继承自另一个类时,这不起作用:

template<typename T>
class serializable
{
    protected:
        serializable() = default;
    ...
    // other stuff
}

struct point : public serializable<point>
{
    float coord[3];
};
point p = {1.f, 2.f, 3.f}; // Doesn't work :(
Run Code Online (Sandbox Code Playgroud)

我尝试添加point() = default;到我的点类,但这也不起作用.如何使用初始化列表初始化点?

c++ inheritance initializer-list c++11 list-initialization

8
推荐指数
1
解决办法
947
查看次数

使用braced-init初始化std :: shared_ptr <std :: map <>>

我有以下shared_ptr内容map:

std::shared_ptr<std::map<double, std::string>>
Run Code Online (Sandbox Code Playgroud)

我想用braced-init初始化它.可能吗?

我试过了:

std::string s1("temp");
std::shared_ptr<std::map<double, std::string>> foo = std::make_shared<std::map<double, std::string>>(1000.0, s1);
Run Code Online (Sandbox Code Playgroud)

但是在使用Xcode 6.3编译时会出现以下错误:

/usr/include/c++/v1/map:853:14: Candidate constructor not viable: no known conversion from 'double' to 'const key_compare' (aka 'const std::__1::less<double>') for 1st argument
Run Code Online (Sandbox Code Playgroud)

我已经尝试了第一个参数(1000.0)的其他变体而没有成功.

有人可以帮忙吗?

c++ stdmap shared-ptr c++11 list-initialization

8
推荐指数
1
解决办法
2038
查看次数

用大括号从double初始化float

为什么编译器(clang,gcc)在执行此操作时没有警告缩小转换

float a{3.1231231241234123512354123512341235123541235};
float a = {double(3.1231231241234123512354123512341235123541235)}
Run Code Online (Sandbox Code Playgroud)

我期待一个警告,因为我使用大括号进行显式值初始化.按照这个答案链接它应该吐出一个错误.

汇编在这里

c++ value-initialization c++11 list-initialization c++14

8
推荐指数
2
解决办法
1013
查看次数

在括号内包装初始化列表有什么影响?

在括号内包装初始化列表有什么影响?它只是列表初始化的另一种形式,还是仅在某些情况下有效?

例如,考虑a:

struct A {
    A(float a, float b) {}
};

int main()
{
    A b(1.0f, 0.0f); // Direct initalization, finds ctor for (float, float)
    A c{1.0f, 0.0f}; // List initalization, finds a matching ctor

    A a({1.0f, 0.0f}); // Is this list initalization... which is expanded?
}
Run Code Online (Sandbox Code Playgroud)

c++ c++11 list-initialization

8
推荐指数
1
解决办法
160
查看次数