我昨天才刚刚了解到,为初始化列表项指定参数是可选的.但是,在这种情况下会发生什么规则?
在下面的示例中,ptr是否会初始化为0,切换为false,而Bar默认构造?我想这个问题有点多余,因为如果未指定的参数值= =未定义的行为,初始化程序列表中几乎没有意义.
我是否也可以指向C++标准中指出初始化列表项未被赋予参数的情况下的行为?
class Bar
{
Bar() { }
};
class SomeClass;
class AnotherClass
{
public:
SomeClass *ptr;
bool toggle;
Bar bar;
AnotherClass() : ptr(), toggle(), bar() { }
// as opposed to...
// AnotherClass() : ptr(NULL), toggle(false), bar(Bar()) { }
};
Run Code Online (Sandbox Code Playgroud) 除非我在initializer_list之前放置constexpr,否则以下内容无法编译:
constexpr std::initializer_list<int> il = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
};
std::array<int, il.size()> a;
Run Code Online (Sandbox Code Playgroud)
但是initializer_list的大小是constexpr:
constexpr size_type size() const;
Run Code Online (Sandbox Code Playgroud) 假设我有以下代码:
#include <vector>
struct Foo
{
int tag = 0;
std::function<void ()> code;
};
int main()
{
std::vector<Foo> v;
}
Run Code Online (Sandbox Code Playgroud)
现在我想要Foo使用特定的向量向量添加新项目,tag而code 不是明确创建临时项目.这意味着我必须添加一个构造函数Foo:
struct Foo
{
inline Foo(int t, std::function<void ()> c): tag(t), code(c) {}
int tag = 0;
std::function<void ()> code;
};
Run Code Online (Sandbox Code Playgroud)
现在我可以使用emplace_back:
v.emplace_back(0, [](){});
Run Code Online (Sandbox Code Playgroud)
但是当我不得不再次这样做 - 第100次 - 使用新创建的结构时,我想:我不能使用大括号初始化器吗?像这样:
#include <vector>
struct Foo
{
int tag = 0;
std::function<void ()> code;
};
int main()
{
std::vector<Foo> v;
v.push_back(Foo{ 0, …Run Code Online (Sandbox Code Playgroud) c++ initialization initializer-list c++11 list-initialization
以下代码编译并运行:
#include <initializer_list>
#include <iostream>
#include <vector>
#include <tuple>
void ext( std::initializer_list<std::pair<double, std::vector<double> >> myList )
{
//Do something
}
///////////////////////////////////////////////////////////
int main(void) {
ext( { {1.0, {2.0, 3.0, 4.0} } } );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
虽然这个没有:
#include <initializer_list>
#include <iostream>
#include <vector>
#include <tuple>
void ext( std::initializer_list<std::tuple<double, std::vector<double> >> myList )
{
//Do something
}
///////////////////////////////////////////////////////////
int main(void) {
ext( { {1.0, {2.0, 3.0, 4.0} } } );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
唯一的区别是,在第一种情况下,ext()函数接受类型initializer_list<pair>(工作)的参数而另一个使用initializer_list<tuple>(不起作用).但是,cplusplus.com表示 …
在阅读有关不同主题的同时,我遇到了一种奇怪的行为,至少对我而言.整个思想起源于auto和括号之间的特殊相互作用.如果你写的东西如下:
auto A = { 1, 2, 3 }
Run Code Online (Sandbox Code Playgroud)
编译器将推断A为a std::initializer_list.奇怪的是,类似的规则不仅适用于auto可能有特殊原因的地方,也适用于其他事情.如果你写下面的内容:
template<typename T>
void f(std::vector<T> Vector)
{
// do something
}
Run Code Online (Sandbox Code Playgroud)
你当然不能这样称呼它:
f({ 1, 2, 3});
Run Code Online (Sandbox Code Playgroud)
即使a std::vector可以被支撑初始化.但是,如果替换std::vectorwith std::initializer_list,则调用有效,编译器将正确推断int为类型T.然而,更有趣的是,在前一种情况下你需要#include <vector>,在后者你不需要#include <initializer_list>.这让我想到并且在测试之后我意识到某种程度上std::initializer_list不需要它自己的标题,所以它在某种程度上是"基础"功能的一部分.
而且,对于所有有意义的事情,std::initializer_list应该以与lambdas相同的方式对标准对象进行可调用对象(在最严格的意义上,即具有a的对象operator()).换句话说,未命名的支撑定义应默认为std::initializer_listlambdas(大多数)是未命名的可调用对象.
这个推理是否正确?此外,这种行为可以改变,如果是这样,怎么样?
更新:initializer_list发现的标题是传递的iostream(非常奇怪).但问题仍然存在:为什么呼叫适用std::initializer_list而不适用std::vector?
我有一堆测试向量,以十六进制字符串的形式呈现:
MSG: 6BC1BEE22E409F96E93D7E117393172A
MAC: 070A16B46B4D4144F79BDD9DD04A287C
MSG: 6BC1BEE22E409F96E93D7E117393172AAE2D8A57
MAC: 7D85449EA6EA19C823A7BF78837DFADE
Run Code Online (Sandbox Code Playgroud)
我需要以某种方式将这些内容添加到C++程序中,而无需进行太多编辑.有各种选择:
0x6B,0xC1,0xBE,...但我最终使用的是:
因为好玩.我定义了一个帮助器类HexByteArray和一个用户定义的文字运算符HexByteArray operator "" _$ (const char* s),它解析表单的字符串"0xXX...XX",其中XX...XX是偶数个十六进制数字.HexByteArray包括转换运算符const uint8_t*和std::vector<uint8_t>.所以现在我可以写例如
struct {
std::vector<uint8_t> MSG ;
uint8_t* MAC ;
} Test1 = {
0x6BC1BEE22E409F96E93D7E117393172A_$,
0x070A16B46B4D4144F79BDD9DD04A287C_$
} ;
Run Code Online (Sandbox Code Playgroud)
哪个很好用.但现在我的问题是:我可以为阵列做这个吗?例如:
uint8_t MAC[16] = 0x070A16B46B4D4144F79BDD9DD04A287C_$ ;
Run Code Online (Sandbox Code Playgroud)
甚至
uint8_t MAC[] = 0x070A16B46B4D4144F79BDD9DD04A287C_$ ;
Run Code Online (Sandbox Code Playgroud)
我看不出如何做这项工作.要初始化一个数组,我似乎需要一个std::initializer_list.但据我所知,只有编译器可以实例化这样的东西.有任何想法吗?
这是我的代码:
HexByteArray.h
#include <cstdint>
#include <vector>
class HexByteArray
{
public:
HexByteArray …Run Code Online (Sandbox Code Playgroud) 受到这个答案的启发,我尝试了下一个例子:
#include <map>
#include <string>
#include <iostream>
int main()
{
const std::map< int, std::string > mapping = {
1, "ONE",
2, "TWO",
};
const auto it = mapping.find( 1 );
if ( mapping.end() != it )
{
std::cout << it->second << std::endl;
}
else
{
std::cout << "not found!" << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
编译失败,出现下一条错误消息(g ++ 4.6.1):
gh.cpp:11:5: error: could not convert '{1, "ONE", 2, "TWO"}' from '<brace-enclosed initializer list>' to 'const std::map<int, std::basic_string<char> >'
Run Code Online (Sandbox Code Playgroud)
我知道如何解决它:
const std::map< int, …Run Code Online (Sandbox Code Playgroud) 从C++ 11开始,标准库容器和std::string构造函数都采用初始化列表.这个构造函数优先于其他构造函数(甚至,正如@ JohannesSchaub-litb在评论中指出的那样,甚至忽略了其他"最佳匹配"标准).当将所有带括号()的构造函数转换为其支撑版本时,这会导致一些众所周知的陷阱{}
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
#include <string>
void print(std::vector<int> const& v)
{
std::copy(begin(v), end(v), std::ostream_iterator<int>(std::cout, ","));
std::cout << "\n";
}
void print(std::string const& s)
{
std::cout << s << "\n";
}
int main()
{
// well-known
print(std::vector<int>{ 11, 22 }); // 11, 22, not 11 copies of 22
print(std::vector<int>{ 11 }); // 11, not 11 copies of 0
// more surprising
print(std::string{ 65, 'C' }); // AC, not 65 …Run Code Online (Sandbox Code Playgroud) 我有一个关于卷括号括号列表的不同含义的问题.
我知道C++ 03不支持C++ 11 initializer_list.然而,即使没有-std=c++11编译器标志,gcc 6.3 也会interpolate使用以下代码正确初始化:
map<string, string> interpolate = { { "F", "a && b && c" }, { "H", "p ^ 2 + w" }, { "K", "H > 10 || e < 5" }, { "J", "F && !K" } };
Run Code Online (Sandbox Code Playgroud)
我被问到为什么这会起作用,我意识到我没有答案.这是一个Brace-Init-List,但我们从初始化标准容器的方式通常是通过initializer_list.那么非C++ 11代码如何完成初始化呢?
考虑以下最小示例:
#include <iostream>
struct X {
X() { std::cout << "Default-ctor" << std::endl; }
X(std::initializer_list<int> l) {
std::cout << "Ilist-ctor: " << l.size() << std::endl;
}
};
int main() {
X a{};
X b({}); // reads as construct from {}
X c{{}}; // reads as construct from {0}
X d{{{}}}; // reads as construct from what?
// X e{{{{}}}}; // fails as expected
}
Run Code Online (Sandbox Code Playgroud)
我对 a、b 和 c 没有任何疑问,一切都很清楚
但我不明白为什么 d 有效
d 中这对额外的大括号代表什么?我查了 C++20 标准,但我找不到答案。clang 和 gcc …