簡體   English   中英

不抄襲的班級成員

[英]Class member without copying

我正在嘗試為https://www.leetcode.com上的編碼挑戰編寫解決方案。 leetcode 中解決方案的入口點是一個名為Solution的類的方法。 它們控制方法的名稱,每個問題的名稱都不同。

我正在研究一個有點復雜的問題方法,為了管理復雜性,我編寫了很多輔助函數。 大多數輔助函數都需要一些相同的變量,例如vector<int>我必須搜索一些東西。

我想避免將這些變量傳遞給我編寫的每個輔助函數 我試圖通過使它們成為Solution成員變量來做到這一點。 我通常用像int這樣的原始變量來做這件事,這不會影響空間復雜度,但我剛剛嘗試用一個向量來做,當我嘗試堅持使用常量空間解決方案時,副本確實會影響空間復雜度.

我如何將向量存儲為類的成員變量而不復制它,最好不使用指針 我不想更改我的代碼來處理指針。

這是尋找數組的最小值和最大值的假裝問題的最小示例。 如果我給出問題的解決方案,他們將通過將測試用例傳遞給Solution().findMaximumAndMinimum(testCase);來測試我的程序Solution().findMaximumAndMinimum(testCase); .

class Solution {
    vector<int> numbers;

    pair<int, int> findMaximumAndMinimum(vector<int>& A) {
        numbers = A;
        return {findMinimum(), findMaximum()};
    }

    int findMaximum() {
        auto maximum = numbers.front();
        for (auto number : numbers) {
            if (maximum < number) {
                maximum = number;
            }
        }

        return maximum;
    }

    int findMinimum() {
        auto minimum = numbers.front();
        for (auto number : numbers) {
            if (minimum > number) {
                minimum = number;
            }
        }

        return minimum;
    }
};

我要更改的是代碼段的第 5 行: numbers = A 這將導致A被復制到numbers 我不希望復制發生:我正在競爭制定一個盡可能少的時間和空間的解決方案,而復制我正在搜索的向量肯定會占用大量空間。

總結:我正在嘗試制定一個看起來有點像上面的解決方案,但是針對一個不同且更難的問題。 上面的代碼段在顯示我想要的內容時故意設計得簡單。 我想避免將A顯式傳遞給Solution的其他方法。

背景:

  • 我最初嘗試將向量轉換為引用成員vector<int>& numbers ,但我遇到了構造函數的麻煩。 我相信在這種情況下我無法使用默認構造函數,因此它被報告為“已刪除”,正如此答案所述。
  • Leetcode 將使用默認構造函數調用我的類。 我對此無能為力。
  • 也許我可以在Solution放置一個類並改用這個類,在那里我可以控制類的對象的構造方式,因此引用成員變量不會造成麻煩,但我不想訴諸於此。 我不希望我的程序開始時縮進兩次。

PS:歡迎提出關於如何不通過引用類的許多方法來傳遞A的建議。 請記住這些約束:我的解決方案的入口點是一個名為Solution的類的方法,我無法控制此方法的名稱。 不歡迎有關解決上述問題的不同方法的建議,因為以上是人為的 MWE

這是我的問題的一種可能答案,但我想避免 如果我可以控制Solution構造方式,那么作為引用的成員變量就不是問題。 所以我讓__actualSolution成為一個我可以完全控制它的構造方式的類,然后在 leetcode 知道的類中使用__actualSolution 但是……這看起來很復雜,很難理解。 我提出這個問題的目的是盡可能讓復雜的程序保持可讀性。

class __actualSolution {
    private:
        vector<int>& numbers;
        __actualSolution(vector<int>& A) : numbers(A) {}

    public:
        static pair<int, int> findMaximumAndMinimum(vector<int>& A) {
            auto s = __actualSolution(A);
            return {s.findMinimum(), s.findMaximum()};
        }

        int findMaximum() {
            auto maximum = numbers.front();
            for (auto number : numbers) {
                if (maximum < number) {
                    maximum = number;
                }
            }

            return maximum;
        }

        int findMinimum() {
            auto minimum = numbers.front();
            for (auto number : numbers) {
                if (minimum > number) {
                    minimum = number;
                }
            }

            return minimum;
        }
};

class Solution {
    public:
        pair<int, int> findMaximumAndMinimum(vector<int>& A) {
            return __actualSolution::findMaximumAndMinimum(A);
        }
}

我希望從進一步的答案中得到避免像上述那樣的事情。 幫助我堅持一個類,並避免將A傳遞給Solution每個方法,請記住,我正在處理的實際問題有更多的輔助函數,而不僅僅是這些人為的兩種方法。

假設您主要關心的是

如何將向量存儲為類的成員變量而不復制它,最好不使用指針?

那么std::move()可能適合您的需要。 但是,為此,您必須同意將函數參數視為右值,從而使其資源被“竊取”而不是被復制。

如果是這種情況,您可以按照以下步驟進行。

class Solution {
public:
    typedef std::pair<int, int> solution;
private:
    std::vector<int> numbers;
    solution s = { INT_MAX, -INT_MAX };
    int& min = s.first;
    int& max = s.second;
public:
    const solution& findMaximumAndMinimum(std::vector<int>& A) {
        numbers = std::move(A);
        min = max = numbers[0];
        for (const auto& value : numbers) {
            if      (value < min) min = value;
            else if (value > max) max = value;
        }
        return s;
    }
};

盡管 Leetcode 提交不包含main() ,但我在此處添加它以說明行為。

int main() {
    std::vector<int> testCase = { 4,7,6,1,5,2 };

    std::cout << "testCase size before 'move()' = " << testCase.size() << std::endl;
    
    Solution::solution s = Solution().findMaximumAndMinimum(testCase);

    std::cout << "testCase size after 'move()' = " << testCase.size() << std::endl;
    std::cout << "Solution = {" << s.first << ", " << s.second << "}";
    return 0;
}

輸出:

//testCase size before 'move()' = 6
//testCase size after 'move()' = 0
//Solution = {1, 7}

從 C++11 開始,STL 容器支持移動語義 除此之外,這意味着每當您在 STL 容器之間進行賦值操作通知編譯器 rhs 參數(也是 STL 容器)可以被視為可移動的右值時,rhs 值將被移動而不是復制。 在大小為n的向量的情況下,這種分配不是提升n 個副本,而是“竊取”與 rhs 關聯的指針及其緩沖區大小。 這非常快,特別是在處理大向量時,因為復雜度從 O( n ) 下降到 O(1)。

您可以在自己的類中嵌入移動語義,但這超出了本問題的范圍。 如果您想深入研究,請參考本文作為起點。

暫無
暫無

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

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