【发布时间】:2013-09-19 08:34:05
【问题描述】:
在我最近查看的一段代码中,使用 g++-4.6 编译得很好,我遇到了一个奇怪的尝试,从 std::unique_ptr 创建一个 std::shared_ptr:
std::unique_ptr<Foo> foo...
std::make_shared<Foo>(std::move(foo));
这对我来说似乎很奇怪。这应该是 std::shared_ptr<Foo>(std::move(foo)); afaik,虽然我对动作并不十分熟悉(而且我知道 std::move 只是一个演员,没有任何动作)。
在此 SSC(NUC*)E 上使用不同的编译器进行检查
#include <memory>
int main()
{
std::unique_ptr<int> foo(new int);
std::make_shared<int>(std::move(foo));
}
编译结果:
- g++-4.4.7 给出编译错误
- g++-4.6.4 编译没有任何错误
- g++-4.7.3 给出 内部编译器错误
- g++-4.8.1 给出编译错误
- clang++-3.2.1 编译没有任何错误
所以问题是:哪个编译器在标准方面是正确的?标准是否要求这是一个无效的声明、有效的声明或者这只是未定义的?
加法
我们已经同意,其中一些编译器(例如 clang++ 和 g++-4.6.4)允许转换,而它们不应该。但是使用 g++-4.7.3(在 std::make_shared<Foo>(std::move(foo)); 上产生内部编译器错误),正确拒绝 int bar(std::move(foo));
由于行为上的巨大差异,我将问题保留原样,尽管部分问题可以通过减少到 int bar(std::move(foo)); 来回答。
*) NUC:不可普遍编译
【问题讨论】:
-
除非
Foo的构造函数采用std::unique_ptr<Foo>,否则它不应该编译。 -
当你的意思是“不编译”时,说“编译时出现正确的错误”是令人困惑的。问题标题令人困惑,您不是从 unique_ptr 创建 shared_ptr,而是从 unique_ptr 创建
int。 -
@JonathanWakely 我调整了配方。但是,我将保持原样。为什么?开发人员的意图是这样创建
std::shared_ptr<Foo>。从unique_ptr创建一个int不是这个问题的重点,而是为什么不同的编译器允许这个语句或者惨遭失败。 -
仅供参考,我检查了
unique_ptr是否可以隐式转换为普通指针(但不是) -
@Naszta 不要写
std::shared_ptr<int> shptr(foo.release());!这是可能导致内存泄漏的危险代码。如果shared_ptr未能分配其引用块并引发异常,则您现在已经泄漏了内存。
标签: c++ c++11 g++ smart-pointers clang++