为什么C ++列表初始化也要考虑常规构造函数? [英] Why does C++ list initialization also take regular constructors into account?

查看:45
本文介绍了为什么C ++列表初始化也要考虑常规构造函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C ++中,当使用initializer_list语法初始化对象时,如果没有其他列表初始化规则适用,则对象的常规构造函数也会参与重载解析.据我了解,以下代码调用X :: X(int)

In C++ when using initializer_list syntax to initialize an object, the regular constructors of the object also participate in overload resolution, when no other list initialization rule applies. As far as I understand it, the following code calls X::X(int)

class X { int a_; X(int a):a_(a) {} );

void foo() {
   X bar{3};
}

但是我不明白,为什么在initializer_lists的上下文中还要考虑常规构造函数.我觉得现在很多程序员都在写X {3}来调用构造函数,而不是X(3)来调用构造函数.我根本不喜欢这种样式,因为它使我认为该对象没有常规的构造函数.

But I don't understand, why regular constructors also are considered in context of initializer_lists. I feel that a lot of programmers now write X{3} to call a constructor instead of X(3) to call the construcor. I don't like this style at all, as it makes me think the object does not have a regular constructor.

initializer_list语法也可以用于调用常规构造函数的原因是什么?现在有理由比常规构造函数调用更喜欢此语法吗?

What is the reason why the initializer_list syntax can also be used to call regular constructor? Is there a reason to now prefer this syntax over regular constructor calls?

推荐答案

从本质上讲,这是一团糟.对于C ++ 11,尝试创建一种统一的方法来初始化对象,而不是其他必要的多种方法:

Essentially it is a mess up. For C++11 it was attempted to create one uniform way to initialize objects instead of multiple approaches otherwise necessary:

  • T v(args ...); (通常情况下)
  • 当对基于堆栈的对象使用默认构造函数时,
  • T d = T();
  • T m((iterator(x)),iterator()); 来对抗最烦人的解析器(请注意第一个参数的括号)
  • T a = {/*一些结构化值*/}; 进行聚合初始化
  • T v(args...); for the usual case
  • T d = T(); when using the default constructor for stack-based objects
  • T m((iterator(x)), iterator()); to fight the Most Vexing Parse (note the extra parenthesis around the first parameter)
  • T a = { /* some structured values */ }; for aggregate initialization

反而发明了统一初始化语法:

Instead the Uniform Initialization Syntax was invented:

T u{ /* whatever */ };

目的是在所有地方都使用统一的初始化语法,而旧的stule会过时.一切都很好,除了 std :: initializer_list< S> 的初始化支持者意识到语法将是这样的:

The intention was that uniform initialization syntax would be used everywhere and the old stule would go out of fashion. Everything was fine except that proponents of initialization from std::initializer_list<S> realized that the syntax would be something like that:

std::vector<int> vt({ 1, 2, 3 });
std::vector<int> vu{{ 1, 2, 3 }};

这被认为是不可接受的,统一的初始化语法受到不可弥补的损害,以使更好

That was considered unacceptable and uniform initialization syntax was irreparably compromised to allow the so much better

std::vector<int> vx{ 1, 2, 3 };

这种混合的问题在于,现在有时不清楚实际含义,而且统一的初始化语法也不再统一.在某些情况下,仍然有必要(尤其是在通用代码中对基于堆栈的对象进行值初始化),但并非在所有情况下都是正确的选择.例如,以下两个符号的意思是相同的东西,但它们并不相同:

The problem with this mixture is that it now is sometimes unclear what is actually meant and uniform initialization syntax isn’t uniform any more. It is still necessary in some contexts (especially to value initialize stack-based objects in generic code) but it isn’t the correct choice in all cases. For example, the following two notations were meant to mean the same thing but they don’t:

std::vector<int> v0(1, 2); // one element with value 2
std::vector<int> v1{1, 2}; // two elements: 1 and 2

tl:博士:初始化程序列表和统一的初始化语法是两个单独的符号.可悲的是,他们发生冲突.

tl;dr: initializer list and uniform initialization syntax are the two separate notations. Sadly, they conflict.

这篇关于为什么C ++列表初始化也要考虑常规构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆