【问题标题】:C++ How to store object in arrays without them deletedC ++如何将对象存储在数组中而不删除它们
【发布时间】:2021-12-21 11:16:45
【问题描述】:

我想就我在学习C++时遇到的这个问题寻求帮助。我试图将对象直接存储到一个数组中,但意识到对象会立即被解构。我不明白为什么会这样。

#include <iostream>

class Thing{
    public:
    ~Thing(){
        std::cout<<"Thing destructing";
    }
};

int main(){
    Thing arr[1];
    arr[0] = Thing();
    int x;
    std::cin>>x;
};

【问题讨论】:

  • Thing(); 创建一个临时对象,然后将其复制/移动到数组中。临时对象必须被销毁
  • 当你遇到这样的问题时,还要添加复制构造函数和赋值运算符,这样你就可以看到正在发生的一切。一般来说,如果你的类需要一个析构函数,它也需要一个复制构造函数和赋值运算符。这是通常称为Rule of Three 的一部分。
  • 如果你是从 C# 或 Java 转向 C++,一个很大的区别是 C# 和 Java 默认使用堆分配和垃圾回收,其中分配保留原始分配,而 C++ 默认使用本地(堆栈)分配和复制)。指针可以在 C++ 中使用,但如果没有垃圾收集,它们就很难正确处理,因此大多被避免。
  • 可能相关:在arr[0] = Thing();:你为什么还要用新的默认构造Thing替换数组中默认构造的Thing

标签: c++ class destructor temporary-objects copy-assignment


【解决方案1】:

在此声明中

arr[0] = Thing();

这里使用了默认的复制赋值操作符,将这个表达式Thing()创建的临时对象赋值给数组的元素。分配后临时对象被销毁。

为了更清楚,运行这个演示程序。

#include <iostream>

class Thing
{
public:
    ~Thing()
    {
        std::cout<<"Thing " << i << " destructing\n";
    }
    
    Thing & operator =( const Thing & )
    {
        std::cout << "Thing " << i << " assigning\n";
        return *this;
    }
    
    Thing() : i( ++n )
    {
        std::cout << "Thing " << i << " constructing\n";
    }

private:    
    size_t i;
    static size_t n;
};

size_t Thing::n = 0;

int main() 
{
    {
        Thing arr[1];
        arr[0] = Thing();
    }
    
    std::cin.get();
    
    return 0;
}

它的输出是

Thing 1 constructing
Thing 2 constructing
Thing 1 assigning
Thing 2 destructing
Thing 1 destructing

【讨论】:

  • 我觉得应该是默认的移动赋值运算符(原来Thing有一个)?
  • @TedLyngmo 由于显式声明了析构函数,因此默认情况下未定义移动赋值运算符。
  • 啊,明白了!谢谢
【解决方案2】:

假设你还不知道。

智能指针

#include <memory>

// ...

int main() {
    std::shared_ptr<Thing> arr[1];
    arr[0] = std::shared_ptr<Thing>(new Thing());

    // ...

    // <-- Is automatically deleted around here.
}

指针

不推荐; 使用指针看起来像:

int main() {
    Thing *arr[1] = {};
    arr[0] = new Thing();

    int x;
    std::cin >> x;

    // WARNING: remember to manually delete.
    delete arr[0];
} // <-- BTW, you don't need semi-colon.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-24
    • 1970-01-01
    • 1970-01-01
    • 2018-08-18
    • 1970-01-01
    • 2019-02-16
    • 2016-07-13
    • 1970-01-01
    相关资源
    最近更新 更多