标签: initializer-list

C++初始化列表中的默认值

我昨天才刚刚了解到,为初始化列表项指定参数是可选的.但是,在这种情况下会发生什么规则?

在下面的示例中,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)

c++ standards initializer-list

14
推荐指数
2
解决办法
5433
查看次数

即使成员函数是constexpr,为什么还需要constexpr?

除非我在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)

c++ initializer-list constexpr c++11

14
推荐指数
1
解决办法
1489
查看次数

我可以使用C++ 11大括号初始化语法来避免为简单聚合声明普通构造函数吗?

假设我有以下代码:

#include <vector>

struct Foo
{
    int tag = 0;
    std::function<void ()> code;
};

int main()
{
   std::vector<Foo> v;
}
Run Code Online (Sandbox Code Playgroud)

现在我想要Foo使用特定的向量向量添加新项目,tagcode 不是明确创建临时项目.这意味着我必须添加一个构造函数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

14
推荐指数
2
解决办法
1577
查看次数

为什么`initializer_list <pair>`和`initializer_list <tuple>`表现不一样?

以下代码编译并运行:

#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表示 …

c++ tuples initializer-list std-pair

14
推荐指数
1
解决办法
955
查看次数

std :: initializer_list,支持初始化和标头

在阅读有关不同主题的同时,我遇到了一种奇怪的行为,至少对我而言.整个思想起源于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

c++ templates initializer-list

14
推荐指数
1
解决办法
613
查看次数

使用C++用户定义的文字初始化数组

我有一堆测试向量,以十六进制字符串的形式呈现:

MSG: 6BC1BEE22E409F96E93D7E117393172A
MAC: 070A16B46B4D4144F79BDD9DD04A287C
MSG: 6BC1BEE22E409F96E93D7E117393172AAE2D8A57
MAC: 7D85449EA6EA19C823A7BF78837DFADE
Run Code Online (Sandbox Code Playgroud)

我需要以某种方式将这些内容添加到C++程序中,而无需进行太多编辑.有各种选择:

  • 手动编辑测试向量到表单中 0x6B,0xC1,0xBE,...
  • 手动编辑测试向量到"6BC1BEE22E409F96E93D7E117393172A"形式,并编写一个函数,在运行时将其转换为字节数组.
  • 编写一个程序来解析测试向量并输出C++代码.

但我最终使用的是:

  • 用户定义的文字,

因为好玩.我定义了一个帮助器类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)

c++ initializer-list user-defined-literals

14
推荐指数
2
解决办法
576
查看次数

为什么在初始化地图时不能省略大括号?

受到这个答案的启发,我尝试了下一个例子:

#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++ initializer-list c++11

13
推荐指数
2
解决办法
5155
查看次数

哪些贪婪的初始化列表示例潜伏在标准库中?

从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++ initializer-list c++11 list-initialization

13
推荐指数
1
解决办法
991
查看次数

为什么GCC 6.3在没有明确的C++ 11支持的情况下编译这个Braced-Init-List代码?

我有一个关于卷括号括号列表的不同含义的问题.

我知道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代码如何完成初始化呢?

c++ gcc initializer-list c++03 list-initialization

13
推荐指数
1
解决办法
1450
查看次数

初始化列表中的空大括号魔术

考虑以下最小示例:

#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)

Godbolt 示例

我对 a、b 和 c 没有任何疑问,一切都很清楚

但我不明白为什么 d 有效

d 中这对额外的大括号代表什么?我查了 C++20 标准,但我找不到答案。clang 和 gcc …

c++ initializer-list c++20

13
推荐指数
2
解决办法
1124
查看次数