在C 中列出初始化,initializer_list和相关问题
List initialization, Initializer_list and related questions in C++
我知道这是一个在stackoverflow上进行了广泛讨论的主题,但是我很难找到彻底的答案,以消除我在c 中的listibalize initialization和initializer_lists of clientibal interization offersion的彻底答案。因此,我将尝试一下自己的问题。
请考虑以下代码段:
class C
{
public :
C(int a, int b, int c) : _a (a), _b(b), _c(c) {}; //initialization_list with ()
//C(int a, int b, int c) : _a{ a }, _b{ b }, _c{ c } {}; //initialization list with {}
private :
int _a, _b, _c;
};
int main()
{
C a(5.3,3.3,4.3); // no list
C b{5.3,3.3,4.3}; // list {}
C c({5.3,3.3,4.3}); // list {}
}
我不明白为什么这两个初始化列表的行为类似?我期望在尝试使用类型_a{a}, _b{b}, _c{c}
的初始化列表创建C类型A的对象A时,以获取有关缩小的编译器错误。但是,没有生成错误,_a, _b and _c
只需存储整数值即可。
仅当使用列表" {}"创建对象B或C时,编译器才能生成狭窄的错误消息。这是为什么?使用{}或()编写初始化列表之间有任何区别,或者行为相同?
是我的下一个问题:
class C
{
public :
//private :
int _a, _b, _c;
};
int main()
{
C a(5,3,4); //obviously doesn't work as no such constructor
C b{5,3,4}; //work only if _a, _b and _c are not private nor protected!
}
第二个语句(带有括号)如何才能在变量是公共的情况下起作用?涉及什么机制?
所以我想更好地理解,除了" narrating Safety" 通过使用列表{}创建对象提供的其他"功能" 提供此列表机制提供?因为在第二个呼叫中,仍然是称为默认的构造函数(因此,不是将initializer_list作为参数的默认构造函数),对吗?
最后,想象一下我的class C
中,我还有另一个构造函数以参数为参数。
class C
{
public :
C() = default; //default constructor
C(int a, int b, int c) : _a (a), _b(b), _c(c) {};
C(std::initializer_list<int> a) { //do some stuffs with the list};
private :
int _a, _b, _c;
};
很明显,如果试图创建一个对象,但将任何数量的整数(实际上为0)(实际上为0),则将调用服用initializer_list的构造函数。但是,如果创建这样的对象:
C c();
或
C c{};
将调用默认构造函数。但是,如果用 3 整数创建对象:
C c(5,2,3);
或
C c{5,2,3};
将调用initializer_list构造函数。规则是这样的:
- 如果可以调用默认的构造函数或初始化列表构造函数,请选择默认构造函数
- 如果可以调用初始化列表和"普通构造函数",请更喜欢初始化器列表构造函数
因此(如果我错了,请纠正我),如果我这样创建我的对象:
C c{5,3,4};
将调用Intiatializer-list构造函数。但是,如果我这样创建我的对象:
C c(5,3,4);
将调用第二个构造函数(以参数为3个INT)。我的问题是:如果我还想提供狭窄的安全性,我该如何使用第二个构造函数而不是Intiatializer-list列表来创建一个对象?(因为如果我在这个问题的第一个示例中这样做,则将调用初始化列表构造函数!)。
请随时检查您的答复,并讨论与列表相关的概念,我在这个问题中尚未谈论。我想对那些很好地掌握。谢谢。
因此,随时都使用卷曲括号,您使用的是汇总初始化,一种初始化方法的结构或类的初始化方法,或者是通过指定器进行初始化的。例如,
#include <iostream>
struct Foo
{
int a;
char b;
};
class Doo
{
public:
double h;
char ch;
};
int main() {
Foo first = {3, 't'};
std::cout << first.b << "n";
//t
Doo second = {'3', 50};
std::cout << second.ch << "n";
//2 interpreted as char
}
在这里,当我们使用{}
初始化类或结构时,它们总是被解释为在类中列出的顺序中。这就是为什么" 2"在ASCII中印刷了" 2"的原因,对应于字符'2'。
构造函数初始化
因此,您还可以使用构造函数初始化列表的相同逻辑,
#include <iostream>
struct Pair
{
int first;
long second;
};
class Couple
{
public:
Pair p;
int g;
public:
Couple(): p{3, 700}, g{3}
{}
};
int main() {
Couple test;
std::cout << test.p.first << "n";
//3
}
在这里,p
旁边的{3, 700}
与Pair p = {3, 700};
在代码中使用的其他位置相同。您基本上使用秩序的汇总初始化。现在,如果我们将配对字段的卷曲括号更改为括号呢?
我们得到此错误
main.cpp: In constructor 'Couple::Couple()':
main.cpp:15:26: error: no matching function for call to 'Pair::Pair(int, int)'
Couple(): p(3, 700), g{3}
那是因为我们没有一个接受两个数字的构造函数。因此,汇总初始化和括号之间的关键区别是,您需要对您使用括号进行的任何特定参数实现构造函数,但是使用卷发括号,您只需使用默认的编译器即可将编译器递给您。
std :: initializer_list是一种不常见的容器形式,用于带有{}
初始化列表中的多个参数。
- 警告处理为错误这里有什么问题
- 使用std::multimap迭代器创建std::list
- 最小硬币更换问题(自上而下方法)
- 为"adjacent"变量赋值时出现问题
- 我的神经网络不起作用 [XOR 问题]
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 在Ubuntu 16.04上安装Cilk时出现问题
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 编译包含字符串的代码时遇到问题
- Project Euler问题4的错误解决方案
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 静态数据成员的问题-修复链接错误会导致编译器错误
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 模板类和继承问题 - 'List'不命名非静态数据成员或基类
- c++中List和Map之间的性能问题
- 关于std::list的基本问题
- 抽象类和虚方法问题:不能将变量' list '声明为抽象类型' aStack
' aStack - iPhone-Cocos2d-Box2d游戏 #include <list> 问题