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

在 C 14 中,constexpr 成员可以更改数据成员吗?

山高峰
2023-03-14

在C 14中,由于<code>constexpr</code>不再是隐式<code>常量</code<,所以<code>constexpr<-code>成员函数是否可以修改类的数据成员:

struct myclass
{
    int member;
    constexpr myclass(int input): member(input) {}
    constexpr void f() {member = 42;} // Is it allowed?
};

共有2个答案

彭宏深
2023-03-14

据我所知,是的。限制来自[dcl.constexpr]:

constexpr函数的定义应满足以下约束:
-它不应是虚拟的(10.3)
-其返回类型应为文本类型
-其每个参数类型都应为文字类型
-其函数体应为=delete=default或不包含

    < li >一个asm定义, < li >一个< code>goto语句, < li >一个试块,或者 < li >非文字类型、静态或线程存储持续时间变量的定义,或者不执行初始化的变量的定义。

该功能满足所有这些要求。

支淮晨
2023-03-14

是的,我相信这种变化始于提案N3598: constexpr成员函数和隐式const,并最终成为N3652:放松constexpr函数的约束的一部分,它改变了第< code>7.1.5节第< code>3段白名单中函数体中允许的内容:

其函数体应为 = 删除、= 默认值或仅包含

  • 空语句,
  • static_assert-声明
  • 不定义类或枚举的typedef声明和别名声明,
  • 使用-声明,
  • 使用-指令,
  • 和正好一个返回语句;

到黑名单:

其函数体应为 = 删除、= 默认值或不包含的复合语句

    < li >一个asm定义, < Li > goto语句, < li >一个试块,或者 < li >非文字类型、静态或线程存储持续时间变量的定义,或者不执行初始化的变量的定义。

并在第C.3.3节第7条“声明”中增加了以下注释:

更改:constexpr 非静态成员函数不是隐式 const 成员函数。

基本原理:允许constexpr成员函数改变对象是必要的。

对原始功能的影响:有效的C 2011代码可能无法在本国际标准中编译。例如,以下代码在C 2011中有效,但在本国际标准中无效,因为它用不同的返回类型声明了同一个成员函数两次:

struct S {
 constexpr const int &f();
 int &f();
};
 类似资料:
  • 我遇到了我不明白的情况。有人能很好地解释为什么第一个代码编译正确,而第二个代码出错: 错误:“TestClass::z”的值在常量表达式中不可用。} - ^ 注意:“int TestClass::z”不是const static int z;" 工作代码: 但是当我尝试使 静态时,我得到上述错误: 附言:我正在使用mingw32-g 4.8.1

  • 我试图在C类中实现一个返回模板参数的constexpr成员函数。代码应该是c 11兼容的。然而,当模板化的类还包含STL容器作为数据成员时,比如STD::vector(const expr成员函数不涉及它),我会遇到编译问题。 以下代码给出了一个最小的示例: 代码使用命令正确编译 g -std=c 14 -O3 快速测试.cpp -o 测试 -Wall clang-STD = c 11-O3 qu

  • 我正在尝试使用 更改 联盟的活动成员,并在构造函数使用初始值设定项列表与成员初始化其成员时出现以下错误。有人可以解释为什么吗? 错误:

  • 联机编译器URL:http://goo.gl/jni6Em 编译器:clang 3.4(带有-std=c 1y) 系统:Linux 3.2 如果删除L2,则编译此代码。如果我添加L2,编译器会抱怨“常量表达式中不允许修改常量限定类型‘const int‘的对象”。我不是语言律师,所以我不确定这是否属实。然而,若确实如此,为什么编译器并没有抱怨L1,因为它也将A()作为constexpr调用?这是叮

  • 我试图通过一个方法更改对象成员的值,但我不明白为什么它在这种特定情况下不起作用: 当我在全局范围内创建对象时,我不明白为什么值是3。msvc和clang在两种情况下都显示5,但不显示gcc。谁错了?

  • 我想出了这个类: 这里是用法: 问题: 为什么使用作为返回表达式编译得很好(Z不是instexpr)。 如何调用和方法的对象() ? 中的行为在编译器中是不同的。MSVC可以使用作为模板参数进行编译,而GCC(IdeOne)不会编译它。 对于一个编译器来说< code>constexpr GetX是真正的< code>constexpr,但是对于另一个编译器来说,如果涉及到< code>X Z就不