繁体   English   中英

C ++ 11中“return {}”语句的含义是什么?

[英]What does “return {}” statement mean in C++11?

这句话是什么?

return {};

在C ++ 11中指出,何时使用它而不是(比如说)

return NULL;

要么

return nullptr;

return {}; 表示“返回使用空list-initializer初始化的函数返回类型的对象”。 确切的行为取决于返回的对象的类型。

来自cppreference.com (因为OP标记为C ++ 11,我排除了C ++ 14和C ++ 17中的规则;请参阅该链接以获取更多详细信息):

  • 如果braced-init-list为空且T是具有默认构造函数的类类型,则执行值初始化。
  • 否则,如果T是聚合类型,则执行聚合初始化。
  • 否则,如果T是std :: initializer_list的特化,则根据上下文,从braced-init-list直接初始化或复制初始化T对象。
  • 否则,T的构造函数分为两个阶段:

    • 将std :: initializer_list作为唯一参数的所有构造函数,或作为第一个参数,如果其余参数具有默认值,将检查所有构造函数,并通过重载决策与std :: initializer_list类型的单个参数进行匹配
    • 如果前一个阶段没有产生匹配,则T的所有构造函数都参与对由braced-init-list元素组成的参数集的重载解析,并限制只允许非缩小转换。 如果此阶段产生显式构造函数作为复制列表初始化的最佳匹配,则编译失败(注意,在简单的复制初始化中,根本不考虑显式构造函数)。
  • 否则(如果T不是类类型),如果braced-init-list只有一个元素,并且T不是引用类型或者是与元素类型兼容的引用类型,则T是直接的 - 初始化(在直接列表初始化中)或复制初始化(在复制列表初始化中),但不允许缩小转换。

  • 否则,如果T是与元素类型不兼容的引用类型。 (如果引用是非常量左值引用,则会失败)
  • 否则,如果braced-init-list没有元素,则T是值初始化的。

在C ++ 11之前,对于返回std::string的函数,你会写:

std::string get_string() {
    return std::string();
}

使用C ++ 11中的大括号语法,您不需要重复类型:

std::string get_string() {
    return {}; // an empty string is returned
}

当函数返回指针类型时,应该使用return NULLreturn nullptr

any_type* get_pointer() {
    return nullptr;
}

但是,自C ++ 11以来不推荐使用NULL因为它只是整数值(0)的别名,而nullptr是一个真正的指针类型:

int get_int() {
    return NULL; // will compile, NULL is an integer
}

int get_int() {
    return nullptr; // error: nullptr is not an integer
}

这可能令人困惑:

int foo()
{
  return {};   // honestly, just return 0 - it's clearer
}

这可能不是:

SomeObjectWithADefaultConstructor foo()
{
  return {};
  // equivalent to return SomeObjectWithADefaultConstructor {};
}

return {}; 表示{}返回值的初始值设定项 返回值使用空列表进行列表初始化。


以下是基于C ++标准中[stmt.return]的返回值的一些背景知识:

对于按值返回的函数(即返回类型不是引用而不是void ),有一个名为返回值的临时对象。 此对象由return语句创建,其初始值设定项取决于return语句中的内容。

返回值一直存在,直到调用该函数的代码中的完整表达式结束; 如果它有类类型,那么它的析构函数将运行,除非它的生命周期延长了调用者直接将引用绑定到它。

返回值可以通过两种不同的方式初始化:


假设T是函数的返回类型,则注意return T{}; return {}不同:在前者中,创建临时T{} ,然后从该临时复制初始化返回值

如果T没有可访问的copy / move-constructor,则无法编译,但return {}; 即使那些构造函数不存在,也会成功。 因此, return T{}; 可能会显示复制构造函数等的副作用,虽然这是复制省略,因此可能不会。


下面简要回顾一下C ++ 14中的列表初始化 (N4140 [dcl.init.list] / 3),其中初始化器是一个空列表:

  • 如果T是一个聚合,那么每个成员都是从它的大括号或初始化器中初始化的,如果它有一个,否则好像是{} (所以递归地应用这些步骤)。
  • 如果T是具有用户提供的默认构造函数的类类型,则调用该构造函数。
  • 如果T是具有隐式定义的或= default ed默认构造函数的类类型,则对象将进行零初始化 ,然后调用默认构造函数。
  • 如果Tstd::initializer_list ,则返回值为空这样的列表。
  • 否则(即T是非类型 - 返回类型不能是数组),返回值为零初始化。

这是方法返回类型的新实例的一种简写。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM