C++定义构造函数使对象成为非 POD
C++ defining constructor make object non POD
如果我有一个简单的结构Foo
,定义如下,它是一个 POD:
#include <iostream>
#include <type_traits>
struct Foo {
int a;
int b;
bool c;
};
int main() {
std::cout << (std::is_pod<Foo>::value ? "POD" : "NON POD") << 'n'; // Prints "POD"
}
现在想象一下,我想默认启动成员并直接执行以下操作:
struct Foo {
int a;
int b;
bool c = true;
};
结构不再是 POD!即使使用这样的构造函数:
struct Foo {
int a;
int b;
bool c;
Foo() : a(0), b(0), c(false) {}
};
Foo已经失去了它的PODness...
现在棘手的部分开始了。想象一下,我想添加一个构造函数,a
:
struct Foo {
int a;
int b;
bool c;
Foo(int a) : a(a), b(0), c(false) {}
};
现在Foo绝对不是POD。但是,如果添加默认构造函数:
struct Foo {
int a;
int b;
bool c;
Foo() = default;
Foo(int a) : a(a), b(0), c(false) {}
};
Foo现在是一个POD!
如您所见,即使我只想使用第二个示例中的默认值,我也会丢失 PODness,但只要我定义显式默认构造函数,我就可以重新获得它。
所以问题是:我们是否应该始终添加一个默认构造函数,以便我们可以从类的 PODness 中受益并提高性能?仅仅因为我想默认初始化某些成员而失去性能太糟糕了......
换句话说,像第二个示例中那样定义默认值会使结构非 POD 和不平凡,这在性能方面很糟糕,那么我如何默认初始化值并保持结构简单?一个简单的解决方案是定义一个返回默认初始化 Foo 的initFoo
函数,例如:
Foo initFoo() {
Foo foo;
foo.a = 0;
foo.b = 1;
foo.c = true;
return foo;
}
但这还不是很C++,但无论如何,这样做是正确的吗?
我们是否应该始终添加一个默认构造函数,以便我们可以从类的 PODness 中受益
如果您希望一个类是 POD,那么它必须是微不足道的默认可构造的,以及其他要求。
实现该要求的一种方法是不声明任何构造函数或默认成员初始化器。另一种方法是将默认构造函数定义为默认值。如果希望类具有任何非默认构造函数,则后者是唯一的方法。
就PODness 而言,选择哪种方法并不重要。
但这是正确的做法吗?
initFoo
是返回具有特定值的Foo
的正确方法。就个人而言,我在局部变量中看不到价值,而是会这样做:
return {
0,
1,
true,
};
不幸的是,我们从初始化器中丢失了成员名称,至少在 C++20 之前我们可以编写:
return {
.a = 0,
.b = 1,
.c = true,
};
- Qt5 远程对象 + 自定义类型,但不在 POD 中
- C++定义构造函数使对象成为非 POD
- 具有非 POD 对象的 GLib 异步队列
- 泛型运算符== 用于非 pod 对象
- 初始化新对象时C++默认构造函数和 POD 问题
- 通过指向其基的指针删除 POD 对象是否安全
- 为什么不能用memcpy复制非POD对象?
- 从数据成员(一次性嵌套类)中获取非 POD 对象的地址
- 使用static_cast铸造POD对象
- POD 类对象初始化是否需要构造函数
- 使用 memcpy 移动非 POD C++对象是否总是调用未定义行为
- C++不能传递非 POD 类型的对象
- 函数作用域的静态非 Pod 对象初始化
- 在共享库中全局声明的非pod对象的语义是什么?
- 从动态创建的数组构造pod对象时,是否推荐使用placement new ?
- 对于非pod对象,xvalue和右值在允许使用或行为方面的差异示例是什么?
- 为什么常量 POD 对象中的字段本身不是常量?
- 如何比较POD类型的对象
- C++标准是否允许对具有常量成员的 POD 对象进行零初始化
- 具有公共链接的非 POD 对象:应该发生什么?