构造函数是特殊的成员函数,constexpr构造函数有其他特殊的规则。
constexpr没有必须要返回值的规定吧?
cppreference.com 创建账户 页面 讨论 变换 查看 编辑 历史 Adobe Creative Cloud for Teams starting at $29.99 per month. ads via Carbon constexpr 指定符(C++11 起) C++ C++ 语言 声明 constexpr - 指定变量或函数的值能出现在常量表达式中 解释 constexpr 指定符声明可以在编译时求得函数或变量的值。然后这些变量和函数(若给定了合适的函数参数)可用于仅允许编译时常量表达式之处。用于对象或非静态成员函数 (C++14 前)声明的 constexpr 指定符隐含 const 。用于函数声明的 constexpr 指定符或 static 成员变量 (C++17 起)隐含 inline 。 constexpr 变量必须满足下列要求: 其类型必须是字面类型 (LiteralType) 。 它必须被立即初始化 其初始化的完整表达式,包括所有隐式转换、构造函数调用等,都必须是常量表达式 constexpr 函数必须满足下列要求: 它必须非虚 (C++20 前) 其返回类型必须是字面类型 (LiteralType) 其每个参数都必须是字面类型 (LiteralType) 至少存在一组参数值,使得函数的一个调用能为被求值的核心常量表达式的子表达式(对于构造函数为足以用于常量初始化器) (C++14 起)。不要求对这点的诊断。 函数体必须是被删除或被默认化,或只含有下列内容: 空语句(平凡分号) static_assert 声明 不定义类或枚举的 typedef 声明及别名声明 using 声明 using 指令 恰好一条 return 语句。 (C++14 前) 函数体必须是被删除或被默认化,或含有下列内容外的任何语句: asm 声明 goto 语句 拥有异于 case 和 default 标号的语句 try 块 非字面类型的变量定义 静态或线程存储期变量的定义 不进行初始化的变量定义。 (C++14 起) constexpr 构造函数必须满足下列要求: 其每个参数都必须是字面类型 (LiteralType) 。 该类不能有虚基类 该构造函数不可有函数 try 块 构造函数体必须被删除或被默认化或只含有下列内容: 空语句 static_assert 声明 不定义类或枚举的 typedef 声明及别名声明 using 声明 using 指令 (C++14 前) 构造函数体的复合语句必须满足 constexpr 函数体的限制 (C++14 起) 对于 class 或 struct 的构造函数,每个子对象和每个非变体非 static 数据成员必须被初始化。若类是类联合体类,对于其每个非空匿名联合体成员,必须恰好有一个变体成员被初始化 对于非空 union 的构造函数,恰好有一个非 static 数据成员被初始化 每个被选作初始化非 static 成员和基类的构造函数必须是 constexpr 构造函数。 对于 constexpr 函数模板和类模板的 constexpr 函数成员,必须至少有一个特化满足上述要求。其他特化仍被认为是 constexpr ,尽管常量表达式中不能出现这种函数的调用。 注意 因为 noexcept 运算符始终对常量表达式返回 true ,故它可用于检查具体特定的 constexpr 函数调用是否采用常量表达式分支: constexpr int f(); constexpr bool b1 = noexcept(f()); // false, constexpr 函数未定义 constexpr int f() { return 0; } constexpr bool b2 = noexcept(f()); // true, f() 是常量表达式 (C++17 前) constexpr 构造函数允许用于非字面类型的类。例如, std::unique_ptr 的默认构造函数是 constexpr ,允许常量初始化。 引用变量可声明为 constexpr (其初始化器必须是引用常量表达式): static constexpr int const& x = 42; // 到 const int 对象的 constexpr 引用 // (该对象拥有静态存储期,因为 static 引用续命) 关键词 constexpr 示例 计算阶乘的 C++11 constexpr 函数的定义,及扩展字符串字面量的字面类型: 运行此代码 #include <iostream> #include <stdexcept> // C++11 constexpr 函数使用递归而非迭代 // ( C++14 constexpr 函数可使用局部变量和循环) constexpr int factorial(int n) { return n <= 1? 1 : (n * factorial(n - 1)); } // 字面类 class conststr { const char* p; std::size_t sz; public: template<std::size_t N> constexpr conststr(const char(&a)[N]): p(a), sz(N - 1) {} // constexpr 函数通过抛异常来提示错误 // C++11 中,它们必须用条件运算符?:这么做 constexpr char operator[](std::size_t n) const { return n < sz ? p[n] : throw std::out_of_range(""); } constexpr std::size_t size() const { return sz; } }; // C++11 constexpr 函数必须把一切放在单条 return 语句中 // ( C++14 无该要求) constexpr std::size_t countlower(conststr s, std::size_t n = 0, std::size_t c = 0) { return n == s.size() ? c : 'a' <= s[n] && s[n] <= 'z' ? countlower(s, n + 1, c + 1) : countlower(s, n + 1, c); } // 输出函数要求编译时常量,以测试 template<int n> struct constN { constN() { std::cout << n << '\n'; } }; int main() { std::cout << "4! = " ; constN<factorial(4)> out1; // 在编译时计算 volatile int k = 8; // 不允许使用 volatile 者优化 std::cout << k << "! = " << factorial(k) << '\n'; // 运行时计算 std::cout << "the number of lowercase letters in \"Hello, world!\" is "; constN<countlower("Hello, world!")> out2; // 隐式转换到 conststr } 输出: 4! = 24 8! = 40320 the number of lowercase letters in "Hello, world!" is 9 缺陷报告 下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。 DR 应用于 出版时的行为 正确行为 CWG 1911 C++14 不允许对于非字面类型的 constexpr 构造函数 在常量初始化中允许 CWG 2004 C++14 在常量表达式中允许复制/移动有 mutable 成员的联合体 去除 mutable 变体隐式复制/移动的资格 CWG 2163 C++14 尽管 goto 在 constexpr 函数中被禁止,标号却得到允许 标号也被禁止 CWG 2268 C++14 cwg 2004 曾禁止了复制/移动有 mutable 成员的联合体 若该对象在常量表达式中创建,则允许 参阅 常量表达式 首页社区专页新闻动态最近更改随机页面帮助 链入页面相关更改上传文件特殊页面打印版本永久链接页面信息 其他语言 DeutschEnglishEspañolFrançaisItaliano日本語PortuguêsРусский 本页面最后修改于2018年6月18日 (星期一) 23:05。 隐私政策 关于cppreference.com 免责声明 Powered by MediaWiki Powered by GeSHi Hosted by Tiger Technologies
64,637
社区成员
250,559
社区内容
加载中
试试用AI创作助手写篇文章吧