2013-01-08 193 views
0

我想從其中包含的方法創建多個對象的方法調用返回一個勁兒地對象中組合多個對象。在一個單一的返回對象

Results calculate() { 

    Foo f; 
    Bar b; 
    ... 
    Results r(f, b); 
    return r; 
} 


class Results { 

private: 
    ? 

public: 

    Results(Foo& f, Bar& b); 

    Foo? getFoo(); 

    Bar? getBar(); 

} 

a)應Results成員變量是指針?

private: 
    Foo* foo; 
    Bar* bar; 


public: 
    Results(Foo& f, Bar& b) { 
     this->foo = &f; 
     this->bar = &b; 
    } 

b)如果getFoo回報FooFoo&Foo*

+0

你究竟想達到什麼目的?也許最好是通過引用傳遞對象,而不是創建一個包含要返回的對象的新對象。 – Skalli

+0

@Skalli'calculate'方法創建了多個對象,這些對象只能在一起使用。通過引用傳遞輸出參數對我而言在風格上感覺很奇怪,有什麼優勢? – clstaudt

+0

那麼,沒有野生指針是一個優勢。但我喜歡mfontaninis解決方案。但是如果你有兩個以上的物體,你需要一種不同的方法。 – Skalli

回答

2

不,不要這樣做。因爲在calculate(),Foo fBar b是本地對象,當您從此函數返回時,它們將消失。將fb複製到Results

class Results { 
private: 
    Foo foo; 
    Bar bar; 

public: 
    Results(const Foo& f, const Bar& b) : foo(f), bar(b) {} 

    const Foo &getFoo() const { return foo; } 
    const Bar &getBar() const { return bar; } 
} 

更簡單的方法可以是使用std::pair並返回,而不是

std::pair<Foo, Bar> calculate() { 
    Foo f; 
    Bar b; 
    ... 
    return std::make_pair(f, b); 
} 
4

使用C++ 11的元組(或升壓轉換器的,否則),你基本上重新實現它們:

#include <tuple> 

std::tuple<Foo, Bar> calculate() { 
    Foo f; 
    Bar b; 
    ... 
    return std::make_tuple(f, b); 
} 

void test() { 
    Foo f; 
    Bar b; 
    std::tie(f, b) = calculate(); 
} 

注意,這可以很容易地擴展到返回超過2個對象。這就是爲什麼我使用std::tuple而不是std::pair在另一個答案中提到的。

+1

這是非常糟糕的建議。像「tuple」和「pair」這樣的東西對於快速原型設計來說都不錯,但是你真的不希望在生產代碼中看到它們。像'first'這樣的名字根本沒有提供任何有用的信息,並且使閱讀代碼變得更加困難。 –

+0

@JamesKanze即使我同意你的看法,OP似乎只是使用這個代碼來提供「多個返回值」。所以我不認爲在我的代碼片段中提到的內容實際上存在問題;使用std :: tie將避免與元組進行交互。 – mfontanini

+0

@mfontanini元組的缺點是元組的部分是未命名的。如果我返回一個'std :: tuple ',那麼區分第一個和第二個'Foo'很重要?爲了清楚起見,我寧願有方法'getThisFoo'和'getThatFoo'。 – clstaudt

1

一個)號通過在calculate()初始化值,這些變量「管芯」的時候,功能執行完畢。這樣,您之前初始化的指針將指向一個空白空間。

b)考慮私有成員不能是指針,你可以根據需要做到這一點。如果你想讓數據「停留」在對象內部,你可以採取指針或引用(哪一個並不重要)。否則就採取「正常」的變量。

0

我還是有點不確定你想達到什麼目的,但目前你會遇到麻煩: a和b在堆棧中計算,你基本上返回指向它們的指針。但是一旦計算完成並且ab超出範圍,您就有野性指針。這很糟糕。
如果您有更多的返回值,請創建智能指針並將它們返回到對象中。
或者指針傳遞ab計算,並與計算new在堆上創建的對象。但請注意,您必須自行刪除它們,否則最終會發生內存泄漏。 所以基本上,如果你在result有兩個以上的對象,然後添加一個智能指針像std::auto_ptrstd::shared_ptr(或者,如果你不使用C++ 11 boost::shared_ptr

0

一)結果的成員變量應舉行按價值。否則,您將返回本地超出範圍的數據的地址(或引用)。

b)中的getFoo應該返回一個常量引用的對象,或由返回值,在POD類型的情況下。這就是說,考慮改變你的接口來接受類型Foo &和Bar &的I/O參數,填充裏面的變量並且不返回它們。這會避免返回值的兩個副本,否則這些副本是必需的。

您也可以用一個std ::元組替換你Results類:

std::tuple<Foo,Bar> calculate() { 

    Foo f; 
    Bar b; 
    ... 
    return std::tuple(f,b); 
} 

// client code: 
Foo foo; 
Bar bar; 

std::tie(foo, bar) = calculate(); 

編輯:如果你不使用C++ 11(爲std::tuple)考慮boost::tuple代替。