2017-02-22 29 views
2

如果我們有一個非可移動的,不可複製的類和非顯式構造函數,我們可以按照以下方式返回並使用它(在C++ 11中):使用顯式構造函數返回不可複製的不可移動對象

#include <iostream> 
class NonCop 
{ 
public: 
    /*non explicit*/ NonCop(int a, int b) : number(a + b) {} 
    NonCop(const NonCop&) = delete; 
    int number; 
}; 

NonCop get_non_cop() 
{ 
    return {1, 2}; 
} 

int main() 
{ 
    NonCop &&nc = get_non_cop(); 
    std::cout << "three: " << nc.number << std::endl; 
    return 0; 
} 

但是,如果構造函數是顯式的,它不起作用。是否有任何方法在C++ 11/C++ 14中執行此操作,但在NonCop中沒有修改?

目前我正在使用派生自NonCop的解決方法,即「deexplicits」構造函數,但它看起來並不漂亮。

+1

Dupe of [this](http://stackoverflow.com/questions/34263916/is-it-possible-to-return-an-instance-of-a-non-movable-non-copyable-type)爲C++ 11/14。請注意,在C++ 17中,保證副本elision將使代碼編譯。 – NathanOliver

+0

我很困惑,這實際上是有效的,也很困惑,你想這樣做。你不允許調用者不改變地返回同一個對象。我希望這只是一個學術練習,而不是你實際想要做的事情。 – Mehrdad

+0

@Mehrdad:在C++ 03中,您還可以將一個臨時對象綁定到一個const引用,該引用將對象的生存期延長到作用域的末尾。我認爲它被範圍衛士用於愚蠢。 – knivil

回答

1

不幸的是,在這種情況下,你不能返回臨時對象,因爲在通過值表達式返回時,編譯器要求對象的拷貝構造函數是可訪問的,即使這個對象最終將被複制消除。但是,您可以返回std::unique_ptr而不是具體的對象。

std::unique_ptr<NonCop> get_non_cop() { 
    return std::make_unique<NonCop>(1, 2); 
} 

Live Demo

+0

謝謝,我知道,但我需要這個互斥鎖,並且每次都不能接受額外的分配。 – peper0

+0

@ peper0:然後不要使用真正的堆分配器。使用池分配器或其他。 –

2

不,這是不可能的。在沒有隱式移動或複製(編譯器肯定會退出)的情況​​下,沒有機制在從C++ 11或14中的函數返回時調用顯式構造函數。

在C++ 17中,您只需鍵入return NonCop(1,2);,並且由於「有保證的省略」,它不再需要移動或複製構造函數。


但是,這是C++,所以是的,我可以讓你的代碼工作零零開銷。通過作弊,並返回一個不同的類型。

template<class T> 
struct implicit_construct:T { 
    template<class...Ts> 
    implicit_construct(Ts&&...ts): 
    T(std::forward<Ts>(ts)...) // note: this is an EXPLICIT construction 
    {} 
}; 

implicit_construct<NonCop> get_non_cop() 
{ 
    return {1, 2}; 
} 

Live example

implicit_construct<NonCop>來自NonCop,因此您可以將返回值存儲在NonCop&&中。


如果是自己寫NonCop,那麼我會做的就是添加:

struct explicit_construct_t {}; 
// ... 
struct NonCop { 
    // ... 
    template<class...Ts> 
    NonCop(explicit_construct_t, Ts&&...ts): 
    NonCop(std::forward<Ts>(ts)...) 
    {} 
    // ... 
}; 

,這意味着你可以用explicit_construct_t前綴調用它明確的構造函數隱式調用它們:

NonCop get_non_cop() { 
    return {explicit_construct_t{}, 1, 2}; 
} 
相關問題