全部,
当我使用初始化列表格式实例化一个小部件数组时,一个指向成员变量小部件实例的裸指针会编译,但在更改为 std::unique_ptr<> gcc 后会给出有关已删除函数的编译错误。
$ unname -a
Linux .. 3.5.0-21-generic #32-Ubuntu SMP Tue Dec 11 18:51:59 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
$ g++ --版本
g++ (Ubuntu/Linaro 4.7.2-5ubuntu1) 4.7.2
此代码给出以下编译器错误:
#include <stdlib.h>
#include <memory>
class Widget
{
public:
Widget() {}
};
class W1 : public Widget
{
public:
W1() {}
};
class W2 : public Widget
{
public:
W2() {}
};
class WFactory
{
public:
WFactory(const int i) : _w(new W1()) {}
WFactory(const char* s) : _w(new W2()) {}
~WFactory() { _w.reset(nullptr); }
// ~WFactory() { delete _w; } <--- for naked ptr
private:
// NOTE: does not compile
std::unique_ptr<Widget> _w;
// NOTE: does compile
// Widget* _w;
};
int main()
{
std::unique_ptr<Widget> a(new W1()); // <--- compiles fine
WFactory wf[] { 4, "msg" }; // <--- compiler error using unique_ptr<>
}
错误:
$ g++ -o unique_ptr -std=c++11 -Wall unique_ptr.cpp
unique_ptr.cpp: In function ‘int main()’:
unique_ptr.cpp:36:30: error: use of deleted function ‘WFactory::WFactory(const WFactory&)’
unique_ptr.cpp:22:7: note: ‘WFactory::WFactory(const WFactory&)’ is implicitly deleted because the default definition would be ill-formed:
unique_ptr.cpp:22:7: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Widget; _Dp = std::default_delete<Widget>; std::unique_ptr<_Tp, _Dp> = std::unique_ptr<Widget>]’
In file included from /usr/include/c++/4.7/memory:86:0,
from unique_ptr.cpp:2:
/usr/include/c++/4.7/bits/unique_ptr.h:262:7: error: declared here
unique_ptr.cpp:36:30: error: use of deleted function ‘WFactory::WFactory(const WFactory&)’
unique_ptr.cpp:36:14: warning: unused variable ‘wf’ [-Wunused-variable]
我对任何一个都不知所措:幕后的机制会产生删除的 fcxn;或者更简单地说,为什么 std::unique_ptr<> 的表现力与裸 ptr 相比似乎受到限制。
我的问题是:
- 飞行员失误?
- 编译器错误?
- 我可以让我想要的代码在一些改变的情况下工作吗?
谢谢你。
编辑 1
根据您的回答,我很感激,我可以对 WFactory 进行以下更改:
(标记为不道德的代码)
class WFactory
{
public:
WFactory(const WFactory& wf)
{
(const_cast<WFactory&>(wf)).moveto(_w);
}
WFactory(const int i) : _w(new W1()) {}
WFactory(const char* s) : _w(new W2()) {}
~WFactory() { _w.reset(nullptr); }
void moveto(std::unique_ptr<Widget>& w)
{
w = std::move(_w);
}
private:
std::unique_ptr<Widget> _w;
};
现在程序编译并运行。我感谢标准人员出于某种原因编写规范,因此我将我的结果发布为我手头的案例的善意专业化,我真的想强调 ptr 的独特性。
编辑 2
根据乔纳森的回复,以下代码不会抑制隐式移动 ctor:
class WFactory
{
public:
WFactory(const int i) : _w(new W1()) {}
WFactory(const char* s) : _w(new W2()) {}
private:
std::unique_ptr<Widget> _w;
};
请注意,根本没有~WFactory() {..}
。
也许有 ya-ans,但我发现在 Main() 中对 wf[] 使用 c++11 风格的迭代会导致 no-copy-ctor-for-WFactory 错误。那是:
int Main()
..
WFactory wf[] { 4, "msg" };
for ( WFactory iwf : wf ) <---- compiler error again
// ..
for (unsigned i = 0; i < 2; ++i) <--- gcc happy
wf[i] // ..
}
我想新的 c++11 风格的迭代正在做一个对象复制是不言而喻的。