簡體   English   中英

std :: vector在重新分配時不調用析構函數

[英]std::vector doesn't call destructor on reassignment

我正在嘗試使用std::vector來保存一些S實例。 但是,當我重新分配vector的成員時,先前的租戶不會調用析構函數:

#include <iostream>
#include <vector>

struct S {
    int index_;
    S(int index) : index_(index) {
        std::cout << "Calling S " << index_ << " constructor\n";
    }
    S(const S& other) : index_(other.index_) {
        std::cout << "Calling S " << index_ << " copy constructor\n";
    }
    ~S() {
        std::cout << "Calling S " << index_ << " destructor\n";
    }
};


int main()
{
    std::vector<S> v;
    v.reserve(10); // Let's not worry about copy constructors
    std::cout << "# Created vector\n";
    v.emplace_back(0);
    v.emplace_back(1);
    v.emplace_back(2);
    std::cout << "# Replacing\n";
    v[1] = S(3); // This doesn't destruct S(1) that was here

    // I can manually call the destructor before I reassign but is that
    // something I should do()?
    // v[1].~S();

    std::cout << "# End scope\n";
}

輸出量

# Created vector
Calling S 0 constructor
Calling S 1 constructor
Calling S 2 constructor
# Replacing
Calling S 3 constructor
Calling S 3 destructor
# End scope
Calling S 2 destructor
Calling S 3 destructor
Calling S 0 destructor

因此,看起來位置1處的S(1)從未被破壞。 正如我在代碼中指出的那樣,我可以在重新分配析構函數之前手動調用它,但是我不確定這是否是一個好主意。 是,如果不是,您有什么建議? 還可以嗎

與我真正想要的聯系

在實際代碼中,我正在使用二叉樹,我認為使節點成為向量的成員並使用向量的索引指向彼此是很有趣的(讓我獲得連續的內存緩存優勢,而不是32位索引) 64位指針,以及其他一些玩法)。 但是最終,我需要對樹進行一些操作,這意味着移動/刪除元素,因此我希望調用析構函數來刪除元素(並且我將使用std::set或其他方法來跟蹤漏洞向量)。

分配給vector元素將調用副本分配運算符,而不是副本構造函數。 這就是你需要的

struct S {
    int index_;
    S(int index) : index_(index) {
        std::cout << "Calling S " << index_ << " constructor\n";
    }
    S(const S& other) : index_(other.index_) {
        std::cout << "Calling S " << index_ << " copy constructor\n";
    }

    // added
    S& operator=(const S& other) {
        if (this == &other) { return *this; }
        std::cout << "Calling S " << index_ << " copy assignment\n";
        index_ = other.index_;
        return *this;
    }

    ~S() {
        std::cout << "Calling S " << index_ << " destructor\n";
    }
};

分配不會破壞現有對象,而是分配給它。 您可以用更簡單的情況重現它

int main() {
    S s1(1);
    s1 = S(2); // assignment, not destruction/construction. same idea
}

如果您的對象擁有一些資源,您會發現賦值運算符執行與析構函數和復制構造函數相似的操作。 您可以在此處了解有關3規則,規則通過添加移動操作擴展為5規則

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM