C++ C++;-返回常数唯一值

C++ C++;-返回常数唯一值,c++,c++11,C++,C++11,我想知道为什么在编译时出错: const std::unique_ptr<int> get() { return std::make_unique<int>(10); } int main() { const std::unique_ptr<int> value = get(); return EXIT_SUCCESS; } const std::unique_ptr get(){ 返回标准::使_唯一(10); } int

我想知道为什么在编译时出错:

const std::unique_ptr<int> get() { 
    return std::make_unique<int>(10);
}

int main() { 

    const std::unique_ptr<int> value = get();

    return EXIT_SUCCESS;
}
const std::unique_ptr get(){
返回标准::使_唯一(10);
}
int main(){
const std::unique_ptr value=get();
返回退出成功;
}
我得到以下错误:

main.cpp: In function ‘int main()’:
main.cpp:10:44: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]’
     const std::unique_ptr<int> value = get();
main.cpp:在函数“int main()”中:
main.cpp:10:44:错误:使用已删除的函数“std::unique\u ptr::unique\u ptr(const std::unique\u ptr&)[带\u Tp=int;_Dp=std::default\u delete]”
const std::unique_ptr value=get();
当我从
get
签名中删除
const
时,它会正确编译


有没有办法返回一个常量unique_ptr?

因为
unique_ptr
是常量,不能移动,只能复制。不允许复制一个
唯一的\u ptr
(否则它将不是“唯一的”)


如果指针指向的数据应该是常量,那么使用
std::unique_ptr

是实际的
std::unique_ptr
对象应该是常量,还是它指向的数据?@MooingDuck作为返回类型,这很奇怪。否则,一般来说,指向非常量的常量指针并没有什么奇怪的地方。如果使指针指向别处是错误的,但通过指针改变指向的对象是正确的,则指向非常量的常量指针表示并强制执行该操作。如果人们遵循一些常见的做法,将大多数事物设置为常量,除非有理由不设置,那么指向非常量对象的常量指针经常出现。@EliahKagan:pimpl中的
const
指针会使移动/交换比需要的慢,但是是的,一般来说,在某些情况下,常量指针是有意义的。这是一个x/y问题,我不知道为什么它被选得这么高。您声明希望
unique\u ptr
是常量,尽管
const
返回值在像
unique\u ptr
这样的不可复制类型被添加到混合中之前就已经够奇怪了,但没有解释为什么您认为需要这种奇怪。我不觉得“为什么我不能做[没有任何明显理由的奇怪的事情]”的问题是有用的,否则我可以花一整天的时间去发明和发布它们。@moingduck似乎有很多情况下,
const
指针是个好主意,至少如果一个人重视
const
-正确性的话。当然,如果我们能完全控制函数签名,就应该使用一个引用。然而,我想到的一个接收指针的小例子是一个stdlib算法,比如
find\if
在容器中保存指针的范围内(
reference\u wrapper
似乎不值得麻烦&无论如何应该是
const
本身!)。如果有可能在接收函数中意外地改变指针,则不会有好的结果。请注意:由于保证了复制省略,OP的示例必须在C++17中编译。@bogdan确定吗?它不能在带有
-std=c++17
@bogdan的clang、gcc或msvc上编译
std::unique_ptr
复制构造函数和复制赋值运算符标记为
delete
,这意味着它不能用于任何类型的复制,即使可以省略副本。@patatahooligan这些可能是较旧版本的编译器吗?它确实为我使用了这三个版本的最新版本,Clang 5,GCC 7.3,MSVC 15.9进行编译。@Someprogrammerdude这是真的,适用于C++17之前的任何版本。由于采用了,C++17中的规则发生了变化。基本原理和示例见下表。基本上,从与目标相同类型的prvalue初始化不再被视为从可以省略的临时值复制/移动;它基于prvalue显式创建目标对象;再也没有什么可以艾利德的了。