运算符和构造函数
operators and constructor
我有一个类,在那里我实现了自己的构造函数、析构函数、复制构造函数和复制分配运算符。
该类有一组核心成员,我在上面的所有内容中都有这些成员,还有一组"状态变量",我添加这些变量作为一些方法的助手。
这些状态变量从来没有在构造函数中初始化过(只是因为我没有这么做),而是在使用之前初始化过。
因此,复制构造函数和复制赋值对它们没有任何作用。他们只是复制我明确想要的成员。
- 这会是个问题吗
- 没有显式复制的成员(顺便说一句,这些成员中没有指针)会发生什么?
- 它们也不会在构造函数中初始化
- 这会导致任何"隐藏"的问题吗
干杯André
Can this be a problem?
-如果你在使用之前初始化它们,并且不要忘记发布(在指针的情况下),我看不到任何问题。
What happens to members that aren't explicitly copied (btw, no pointers in these members)? they are also not initialized in the constructor
-他们持有垃圾
Can this lead to any "hidden" problems?
-不,如果你是细心的
但我建议您在任何情况下都在构造函数中初始化它们,因为这样更容易捕捉错误,并且使对象始终处于完整状态。例如,捕获nullptr
指针要比捕获垃圾指针或指向已释放对象的指针容易得多。由于在第一种情况下,程序只会崩溃(取消引用空指针是UB,但通常只是崩溃)
此外,如果可能的话,我更喜欢创建局部变量来存储中间结果。如果它不是一个单一的方法中间结果,那么如果在初始化之前在其他方法中使用这个变量,它可能会成为一个陷阱。在这种情况下,最好存储零初始化变量,这样您就可以assert
,在对其进行计算之前,它处于有效状态
如果这些变量是对象状态的一部分,那么它们应该被复制。如果变量不是对象状态的一部分,那么它们就不应该是成员。如果接口中任何函数的结果取决于操作开始前变量的值,则变量是对象状态的一部分。
上面的一般规则很少有例外,特别是有一些成员变量不参与对象的状态(它们通常标记为mutable
),作为同步机制或复杂操作结果的缓存。
回到您的问题,从描述中可以看出,您可能只是将这些成员用作不同成员函数之间的通信机制。接口中的一个函数设置值,然后调用其他读取/修改值的函数。如果是这种情况,请考虑将变量作为参数传递给函数。通过使用成员,可以有效地隐藏函数对这些值的依赖关系,同时向类添加依赖关系。
如果接口中的任何函数访问这些成员,情况会更糟,在这种情况下,在分配(或复制构造)后,源和目标的行为会不同,这打破了复制初始化/分配后源和目标对象等效的假设。
基本上,从实用的角度来看,如果这些成员不是对象状态的一部分,你可能会接受你目前的方法,但我真的会重新考虑这个设计。如果它们确实参与了对象的状态,则无论如何都不应避免复制它们。
从c++的角度来看,这里没有什么问题,但c++并不能保护你免受枪击。几个月后,您可能会调试一个只在发布版本中发生的错误,然后您将花几天时间找出发生这种情况的原因。为什么我的应用程序在Release中工作而在Debug中不工作,有很多问题,其中一个原因是调试堆初始化了分配的内存。
- 构造函数和转换运算符之间的重载解析
- 复制构造函数、赋值运算符C++
- 如果我真的真的想从 STL 容器继承,并且我继承构造函数并删除新运算符,会发生什么?
- 为用户定义的类正确调用复制构造函数/赋值运算符
- C++矢量复制构造函数和赋值运算符是否也复制保留空间?
- 为什么我的运算符 + 重载尽管是通过引用传递的,但仍调用我的复制构造函数?
- 让某个类的 '=' 运算符在声明时运行构造函数
- C++:使用运算符 = 调用多参数构造函数
- 应用于运算符而不是构造函数的显式关键字
- 运算符+ 的规范实现涉及额外的移动构造函数
- 运算符 new 的执行顺序和构造函数的参数
- 非模板 std::reference_wrapper赋值运算符和模板构造函数
- 如果我也使用复制构造函数并且重载 = 运算符,我是否需要析构函数?
- 复制构造函数和赋值运算符的值类实现
- 在构造函数中使用重载运算符?
- 在C++中,我可以在定义自己的复制构造函数后跳过定义赋值运算符吗?
- 将内置类型变量传递给只有一个类类型参数的"+"运算符函数时自动类型转换的构造函数
- C++ 类的构造函数和函数调用运算符 () 重载之间的歧义
- 删除了所有自动生成的构造函数/运算符的类仍然可以从函数返回吗
- 为简单结构定义哪个复制/移动构造函数/运算符