2017-02-22 81 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}; 
} 
相关问题