c + +:通过花括号调用构造函数? [英] c++ : calling constructors via curly braces?

查看:110
本文介绍了c + +:通过花括号调用构造函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

class A 
{
    int value_;
    public:
    A(int value):value_(value){}
};

A get_a1(int value)
{
    return A(value);
}

A get_a2(int value)
{
    return {value};
}


int main()
{
    A a1 = get_a1(1);
    A a2 = get_a2(2);
}

get_a1() get_a2()(如果有)之间有什么区别?

What is the difference between get_a1() and get_a2(), if any ?

return {value}; 的调用方式是什么?(我猜通过花括号调用构造函数"不是引用此的正确方法)

How is return {value}; called ? (I guess "calling constructors via curly braces" is not the proper way to refers to this)

推荐答案

在您的情况下,根本没有区别.但是,如果您稍微修改一下代码,将会有明显的不同!

In your case, there is simply no difference. But if you modify your code a bit, there will be a visible difference!

首先,您可以用不同的方式来构造类型,所有方式均在此处进行描述:初始化

First of all, you can construct your type in different ways, all described here: initilization

如果您的类还提供了一个采用 std :: initializer_list 的构造函数,则会有区别.

The difference come in, if your class provides also a constructor which takes a std::initializer_list.

请参见以下修改/扩展的代码以显示差异:

See the following code modified/extended to show the difference:

class A 
{   
    public:
        A(int value):value_(value){ std::cout << "int" << std::endl;}
        A(const std::initializer_list<int>& ){ std::cout << "list" << std::endl;}
        void print()
        {   
            std::cout << value_ << std::endl;
        }   
    private:
        int value_;
};  

A get_a1(int value)
{   
    std::cout << "()" << std::endl;
    return A(value);
}   

A get_a2(int value)
{
    std::cout << "{}" << std::endl;
    return {value};
}


int main()
{   
    A a1 = get_a1(1);
    a1.print();
    A a2 = get_a2(2);
    a2.print();
}   

如果运行该编,将会看到使用 {} 将使用 std :: initializer_list 并使用()调用构造函数.将使用您的 int 构造函数.

If you run that prog, you will see that using {} will call the constructor with std::initializer_list and using () will use your int constructor.

为什么在标准中对此进行了描述:

Why is described here in the standard:

§13.3.1.7[over.match.list]/p1:

§13.3.1.7 [over.match.list]/p1:

当非聚合类类型为 T 的对象被列表初始化时(8.5.4),重载解析分两个阶段选择构造函数:

When objects of non-aggregate class type T are list-initialized (8.5.4), overload resolution selects the constructor in two phases:

  • 最初,候选函数是 T 类的initializer-list构造函数(8.5.4),参数列表包括初始化程序列表作为单个参数.
  • 如果未找到可行的initializer-list构造函数,则将再次执行重载解析,其中所有候选函数都在其中类 T 的构造函数和参数列表包括初始化程序列表的元素.
  • Initially, the candidate functions are the initializer-list constructors (8.5.4) of the class T and the argument list consists of the initializer list as a single argument.
  • If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class T and the argument list consists of the elements of the initializer list.

如果初始值设定项列表中没有元素,并且 T 具有默认值构造函数,省略第一阶段.在复制列表初始化中,如果选择了 explicit 构造函数,则初始化为格式不正确.

If the initializer list has no elements and T has a default constructor, the first phase is omitted. In copy-list-initialization, if an explicit constructor is chosen, the initialization is ill-formed.

此外,构造函数列表的构造函数不允许缩小!

In addition, initializer list constructors do not allow narrowing!

§8.5.4列表初始化

§8.5.4 List-initialization

(3.4)否则,如果T是类类型,则考虑构造函数.适用枚举构造函数,并通过重载选择最佳的构造函数分辨率([over.match],[over.match.list]).如果转换范围缩小(请参阅下文)转换任何参数,程序格式错误.

(3.4) Otherwise, if T is a class type, constructors are considered. The applicable constructors are enumerated and the best one is chosen through overload resolution ([over.match], [over.match.list]). If a narrowing conversion (see below) is required to convert any of the arguments, the program is ill-formed.

这篇关于c + +:通过花括号调用构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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