什么是平凡函数?

19

[basic.def.odr]/3提到了“非平凡函数”的术语,我在标准中找不到它的定义(N4140)。

[basic.def.odr]/3

变量x在一个潜在求值的表达式中出现,并且应用左值到右值转换(4.1)将x转换为一个不调用任何非平凡函数的常量表达式(5.19),或者如果x是一个对象,则ex是表达式e的可能结果集合的元素之一,其中要么对e应用左值到右值转换(4.1),要么e是一个废弃值表达式(第5条)。这时变量x被odr使用。

2个回答

9
“非平凡函数”是“平凡特殊成员函数”的补集。有一些定义来说明什么是平凡和非平凡的默认/复制/移动构造函数,复制/移动赋值运算符或析构函数 - 这些特殊成员函数只属于特殊成员函数,并决定是否需要在某些情况下调用它们。
这些定义可以在第§12章中找到。
默认构造函数§12.1/4:
如果默认构造函数不是用户提供的且满足以下条件,则为“平凡”:
- 其类没有虚函数(10.3)和虚基类(10.1); - 其类的任何非静态数据成员都没有花括号或等号初始化; - 其类的所有直接基类都有平凡的默认构造函数; - 对于其类的每个非静态数据成员,如果该成员的类型为类类型(或其数组),则该类具有平凡的默认构造函数。
否则,默认构造函数是“非平凡的”。
复制/移动构造函数§12.8/12:
如果对于类X,其复制/移动构造函数不是用户提供的,其参数类型列表等效于隐含声明的参数类型列表,并且满足以下条件,则为“平凡的”:
- 类X 没有虚函数(10.3)和虚基类(10.1); - 类X 没有任何非静态数据成员是易失性限定类型; - 用于复制/移动每个直接基类子对象的构造函数都是平凡的; - 对于X的每个非静态数据成员,如果该成员的类型为类类型(或其数组),则选择用于复制/移动该成员的构造函数是平凡的;
否则,复制/移动构造函数是“非平凡”的。
复制/移动赋值运算符§12.8/26:
如果类X的复制/移动赋值运算符未由用户提供,其参数类型列表等同于隐式声明的参数类型列表,且:该复制/移动赋值运算符是平凡的;类X没有虚函数(10.3)和虚基类(10.1);类X没有易失类型的非静态数据成员;对于每个直接基类,选择了一个复制/移动赋值运算符;对于X的每个非静态数据成员,如果它是类类型(或数组),则选择了一个复制/移动赋值运算符进行复制/移动。否则,该复制/移动赋值运算符是非平凡的。
析构函数 §12.4/5:
如果析构函数未由用户提供且:析构函数不是虚函数,其类的所有直接基类都有平凡的析构函数,其类的所有非静态数据成员如果是类类型(或数组)则每个这样的类都有平凡的析构函数,则析构函数是平凡的。否则,析构函数是非平凡的。

4
我会尽力为您翻译。以下是需要翻译的内容:我只是想了解在[basic.def.odr]/3中使用术语“琐碎函数”的原因。您能否举一个例子,在该示例中,当调用非平凡成员函数(即非平凡构造函数、非平凡析构函数或非平凡复制-移动赋值运算符)时,将考虑类的常量对象是odr使用的情况? - Belloc

0
也许这个小例子可以帮助你理解在 [basic.def.odr]/3 上下文中的非平凡函数。
struct C
{ 
    int l; 
    constexpr C(int _l) : l(_l) { } 
    constexpr C(const C&c) : q(c.l * 2) { } 
}; 
    
int main()
{ 
    constexpr C c{42}; 
    constexpr int m = c.l; 
    
    struct K
    { 
        int foo() { return c.l; } 
    }
    K l; 
    return l.foo(); 
}

如果您查看标准中的以下行:

将 lvalue-to-rvalue 转换(4.1)应用于 x 会产生一个常量表达式(5.19),该表达式不调用任何非平凡函数

这里 c 满足出现在常量表达式中的要求,但是将 lvalue-to-rvalue 转换应用于 a 会调用一个非平凡函数。

为什么会调用一个非平凡函数?

当 lvalue-to-rvalue 转换发生在未评估的操作数或其子表达式中时,不访问所引用对象中包含的值。否则,如果 glvalue 具有类类型,则转换从 glvalue 复制初始化类型为 T 的临时对象,并且转换的结果是临时对象的 prvalue。

因此,使用类 C 的复制构造函数创建了一个 prvalue,由于复制构造函数是用户定义的,它是非平凡的,因此 c 在此处没有 ODR-used。

如果类 X 的复制/移动赋值运算符不是用户提供的,其参数类型列表等效于隐式声明的参数类型列表,则该运算符是平凡的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接