当前位置: 首页 > 知识库问答 >
问题:

C 17中的初始值设定项列表和结构化绑定

景宏朗
2023-03-14

我一直避免像下面这样的初始化

const auto& x = a, y = b;
const int* const x = ptr_1, *const y = ptr_2;  // wot

因为引用和指针限定符不适用于初始化。假设这是初学者学习的第一件事,与之相关的模糊性让我觉得下面的内容更清晰,也更不需要读者思考

const auto& x = a;
const auto& y = b;

有了C17和结构化绑定,我很开心,看到了很多潜力。C17禁止了C14和C11未能修复的东西,auto x{1}是一个int而不是std::initializer\u列表

const auto& [x, y] {a, b};
const auto& [x, y] = {a, b};

后者符合自动推断和初始值设定项列表的新规则,右侧的表达式被视为初始值设定项列表。但对于前一个编译,编译失败,出现以下错误

initializer for variable '[a, b]' with type 'const auto &' contains multiple expressions

有没有什么方法可以用结构化绑定语法声明x和y,而不必求助于元组、对之类的东西?还有,为什么上面的代码示例中前者的代码格式不正确?这种语法有歧义吗?


共有2个答案

哈泰
2023-03-14

不支持此语法。您只能解压重载了std::get的聚合类和对象:https://skebanga.github.io/structured-bindings/

不幸的是,您不能真正使用酷的推导指南,因为您想要引用a而不是元组成员。因此,您必须写出模板参数列表。

#include <tuple>

int main()
{
  int a = 1;
  int b = 2;
  const auto& [x, y] = std::tuple<int&,int&>{a, b};
}

你也不可能像我一样愚蠢,正确地阅读文件。

#include <tuple>

int main()
{
  int a = 1;
  int b = 2;
  const auto& [x, y] = std::forward_as_tuple(a, b);
}

const auto

邓高韵
2023-03-14

可以说,结构化绑定是为了“解包”东西。它不是设计成组合普通声明的方法。这就是<代码>const auto

您的特定尝试违反了[dcl.dcl]/8:

带有标识符列表的简单声明称为结构化绑定html" target="_blank">声明([dcl.struct.bind])。[...] 初始值设定项的形式应为“=赋值表达式””、形式为“{assignment expression}”或形式为“(赋值表达式)”,其中赋值表达式为数组或非并集类类型。

int a = 1, b = 2;
const auto bitand <:x, y:> = std::tie(a, b);

这种结构化绑定声明(非常)大致相当于

const auto bitand __e = std::tie(a, b); // hidden variable
auto and x = std::get<0>(__e);
auto and y = std::get<1>(__e);

(真正的东西使用的是tuple_元素,而不是auto

笔记:

  • const auto bitand适用于隐藏变量,仅适用于隐藏变量xy始终是引用,即使您只写auto;它们的引用是否为const取决于初始值设定项类型的const传播属性

如果我们讨论的是用两个“reference to int”成员解包一个结构等,那么这些语义并不奇怪;在这样的事情上,const实际上并不影响被指对象的constanss。OTOH,如果你想用结构化的绑定声明来完成一些他们不打算做的事情,你会大吃一惊。

 类似资料:
  • 我在这里找到了最初的*C结构化绑定方案。它提出了一种轻松绑定多个返回值的方法,即: 但现在我看到每个人都指向 现在我学习了“列表是{like,this}编写的”,出现了一种新的列表语法?为什么?这里的花括号有什么问题?

  • 我已经在网上搜索了这个问题的答案,但我还没有找到一个满意的答案。我想知道初始化结构和类类型的对象的所有规则是什么,特别是在构造函数与带括号的初始化列表方面。结构与类的规则也不同吗? 让我们假设有一个名为矩形的类或结构。 我尝试用C语言中通常使用的方式初始化矩形r,使用一个普通的带括号的初始值设定项列表。但是,g给出以下错误: 嗯……嗯。。。。乍一看,这并不是很有用的错误消息。然而,我认为它与构造函

  • 我相信现代C初始值设定项列表对于初始化对象非常有用,甚至不需要定义自己的构造函数: 但是,当我的类从另一个类继承时,这不起作用: 我尝试添加

  • Ivor Horton在开始的Visual C 2013中提到了C语言中的“初始化列表”: "对于const或引用类型的类成员,您无法选择如何初始化它们。唯一的方法是在构造函数中使用成员初始化器列表。构造函数主体内的赋值将不起作用。" 我的Visual Studio 2012 express没有编译初始值设定项列表,所以一开始我很困惑,然后我意识到它不受支持。 我的问题是人们如何在初始化器列表之前

  • 我有一个这样的类,除了有多个成员: 我基本上希望对其进行聚合初始化,如下所示: 但由于自定义构造函数的原因,这似乎是不可能的,因此我想使用构造函数参数来模拟它: 这看起来有很多冗余,只是为了在可能的情况下移动和复制,尤其是在成员数量激增的情况下。我想我想要完美的转发? 但是现在我不能像这样使用空的初始化列表调用它: 因为无法推导出初始化列表参数类型。有没有不需要我写的解决方案 ?

  • 我有以下代码: 我希望输出是:“base constructor,test:50”,但事实并非如此,因为构造函数是在初始化之前调用的,没有错误或警告,它只是编译。 有什么方法可以让构造函数在之后被调用吗?或者这是总体上的糟糕设计? 我正在尝试将所有的init方法和它们的调用放入构造函数insted中,这个行为阻止了我这样做。