標籤:

C++ 函數如何返回多值?

不太清楚在項目、團隊中,函數返回多值的寫法。
1.類似C語言,通過傳入多個二級指針,來獲取返回值。
2.只使用函數返回值,多值使用結構體、類包裹起來。

感覺高級語言更傾向與第二種,沒法直接操作內存。

那麼C++,在業內,更傾向哪一種形式呢,有什麼好處?


tuple和tie


有人提到了structured binding。確實好用。

struct result { bool success; std::string result; };
result foo() {
return { true, "hello" };
}
auto [a, b] = foo();
if (a) { std::cout &<&< b &<&< std::endl; } std::tuple& bar() {
return { true, "hello", "world" };
}
auto [x, y, z] = bar();
if (x) {
std::cout &<&< y &<&< "," &<&< z &<&< std::endl; }

感覺structured binding還不完善,比起go之類的還是難用一點。原proposer還加了很多功能,但17中都被刪掉了,只有這幾種簡單情況。c++20應該會改善更多一些。


如果可以用C++17的話,就可以直接用 Structured binding 語法接受多返回值啦~

#include &
#include &

using namespace std;

struct A { int a; A(int a_) : a(a_) {}; };

auto func() { return tuple(A(1), 2, 3); }

int main() {

auto [a, b, c] = func();
cout &<&< a.a &<&< ", " &<&< b &<&< ", " &<&< c &<&< endl; return 0; }

對於沒有默認構造的類型也是可用的。

在線玩-&>[Wandbox]三へ( へ?? ?)へ ????


我習慣傳引用輸入,作為返回值。然後函數本身的返回則用來標識運行狀態。

不過也可以玩多值返回,用std::tuple。
如果使用的框架支持variant,比如c++17、boost、Qt,那麼返回保存variant的容器也行。

如果是單返回值,又要有運行結果,那可以返回值作為函數返回,運行結果不正常時拋異常。其實這才是最標準的方式。

如果返回的東西數據結構比較複雜,那就得考慮定義一個對象或者結構體了


可以考慮Windows Api中非常常用的一種設計,就是函數返回值用來指示函數是否執行成功,而函數參數中提供一個結構體指針,這樣調用返回後,通過返回值查看是否成功,如果成功,那麼獲取結構體中的值,比如:

BOOL WINAPI GetWindowInfo(
_In_ HWND hwnd,
_Inout_ PWINDOWINFO pwi
);

這個函數中,如果執行成功,可以通過pwi輸出參數獲取各種結果。


2個返回值可以用結構。

struct ret{int a;int b}

64位系統支持2個long。

直接返回這個結構,會利用2個寄存器進行返回。


tuple是個方法了,不過如果是老一些的庫維護的話,一般用這種方法

bool getResult(struct outputDat data){}


只是 C99/C++ 用的話返回結構體就行了,但因為機器碼層面只能返回一個機器字,所以編譯後大於機器字大小的結構是隱式傳一個指針進去得到返回值,所以如果要公開 ABI 給其他語言用,最好直接傳個指針進去。


應該是引用,速度快而且比較安全



optional&&> bar1()
{
return make_tuple(true, string("hello"), string("world"));
}
int main()
{
auto tp2 = bar1();
if(tp2) {
bool t1 = std::get&<0&>(*tp2);
string t2 = std::get&<1&>(*tp2);
string t3 = std::get&<2&>(*tp2);
cout&<&<"t1:"&<&

boost::optional(std::optional c++17) + tuple

既可以返回多值,同時直接還可以用返回值判斷是否合法(初始化)


1. 使用Tuple

2. 自己定義一個結構體來返回

3. structured binding

4. 使用參數返回:

形如:

HRESULT createInstance(IUnknown** out1, IUnknown** out2);

HRESULT表示是否返回成功,out1、out2表示返回的指針


std::tuple,std::tie,std::get終於能像python一樣寫代碼了


用cpp不都講究個oo么,應該比較常見常用的是返回類對象或者結構體對象指針之類的。

也可以用out參數的辦法,看你的需要了。


都是用引用


推薦閱讀:

程序員有哪些借口可以讓自己寫的代碼里到處都是Bug並且代碼可讀性很低?
如何在 Visual Studio 上用 C/C++ 寫 Linux 程序?
最短的可以造成 crash 且編譯器無法優化掉的 C++ 代碼是什麼?
在c中為什麼經常看到for( ; ; )這樣的語句,而不直接用while(1)?
為什麼大多數的C++的開源庫都喜歡自己實現一個string?

TAG:C | CC |