[英]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
,但我遇到了構造函數的麻煩。 我相信在這種情況下我無法使用默認構造函數,因此它被報告為“已刪除”,正如此答案所述。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.