clear() 方法,用于在 C++ 中使用 *this = {} 将所有类字段重置为默认值

clear() method for resetting all class fields to their default values using *this = {} in C++

提问人:mw92 提问时间:1/5/2023 最后编辑:mw92 更新时间:1/11/2023 访问量:438

问:

我在嵌入式编程中对 C 有几年的商业经验,但我对 C++ 很陌生,所以我的逻辑中可能缺少一些东西。

上下文:

这可以通过调用实现为 的类的方法将对象的所有字段重置为其默认值。 它给出的结果与使用 .对象的地址不会使用任何一种方式更改,因此它仍然是同一个对象,以防在某些情况下至关重要。aclear()A*this = {}a = A();

问题:

使用一种或另一种方式的真正风险、缺点或优点是什么,尤其是在动态分配期间涉及内存使用问题时? 或者这些解决方案在所有方面都是等价的?

A a;
//(...)
a.clear();


/* Where: */ 
void A::clear()
{
  *this = {};
}

而不是

A a;
//(...)
a = A();

例:

我检查了以下代码:

#include <iostream>
using namespace std;
class A
{
    public:
    int a1{3};
    int b1{0};
    
    void clear()
    {
        *this = {};
    }
};
int main()
{
    cout << "Using a.clear():" << endl;
    {
    A a;
    cout << a.a1 << " " << a.b1 << " address: "<< &a << endl;
    a.a1 = 1;
    a.b1 = 2;
    cout << a.a1 << " " << a.b1 << " address: "<< &a << endl;
    a.clear();
    cout << a.a1 << " " << a.b1 << " address: "<< &a << endl;
    }
    
    cout << endl << "Using a = A():" << endl;
    {
    A a;
    cout << a.a1 << " " << a.b1 << " address: "<< &a << endl;
    a.a1 = 4;
    a.b1 = 5;
    cout << a.a1 << " " << a.b1 << " address: "<< &a << endl;
    a = A();
    cout << a.a1 << " " << a.b1 << " address: "<< &a << endl;
    }
    
    return 0;
}

输出为:

Using a.clear():
3 0 address: 0x7ffc38d8e990
1 2 address: 0x7ffc38d8e990
3 0 address: 0x7ffc38d8e990

Using a = A():
3 0 address: 0x7ffc38d8e988
4 5 address: 0x7ffc38d8e988
3 0 address: 0x7ffc38d8e988

所以不出所料。

巴西, 兆瓦

分配 的 C++ 对象

评论

1赞 Holt 1/5/2023
我认为这是基于意见的。 或者很清楚,每个 C++ 程序员现在都应该知道它的作用,因为可以以多种方式实现。这也“违背”了没有完全“重新初始化”容器的容器的标准。a = {};a = A{};a.clear().clear().clear()
1赞 Michaël Roy 1/5/2023
它不是基于意见的。这种差异是非常可量化的。清除一些变量比分配和清除新缓冲区要便宜得多,那么清除函数肯定比构造 + 移动使用更少的资源并且运行速度更快。不可能有一种情况是构造 + 移动会比 clear() 便宜,它们的成本可能相同,但永远不会便宜。为了获得最佳结果并减少编写的代码,请创建一个默认构造函数调用的 clear() 函数。这在嵌入式设备上尤为重要,因为嵌入式设备中的堆栈空间可能非常宝贵。
2赞 sklott 1/5/2023
最近有一个相关的问题,它可能对你有一些好处:stackoverflow.com/questions/74912106/......

答:

2赞 bolov 1/5/2023 #1

是的,它们在语义上是等价的。你是对的,你不能改变现有对象的地址。

我不明白你为什么要写这个方法。这并不常见,或者是尽可能简单和“清晰”的,每个人都明白这是做什么的。cleara = A{}a = {}

评论

1赞 Michaël Roy 1/5/2023
仅当您的应用程序具有无限资源并且该类仅包含 POD 成员且没有 C 样式数组时,此答案才适用。构造一个对象至少需要一些堆栈空间,而复杂的对象可能需要堆内存分配,即使在构造时也是如此。
1赞 mw92 1/5/2023
您好博洛夫, 如果 a.clear() 在代码中被多次使用,并且在某些时候有必要在对象中保留一些信息而不是使用 clear 来重新实现该方法,而不是使用 .A::clear()a = A()
0赞 Connor Clark 6/8/2023
当类太大而无法容纳堆栈空间时,一个好的解决方法是声明一个静态默认值(如),然后在您的方法中执行。static myclass* myclass_default = new myclass;*this = *myclass_defaultclear