jma*_*jma 1 c++ unique-ptr c++14
如果我没看错,cppreference说以下两个构造对于 C++14 及更高版本中的非数组类型应该是等效的:
make_unique<T>(T());
unique_ptr<T>(new T());
Run Code Online (Sandbox Code Playgroud)
我显然没有理解一个微妙之处。这是一个示例(带有标题和脚手架的完整文件在这里。在示例中,我希望cmp3和cmp4具有相同的效果,但cmp4不会编译。
template <typename T>
class DbCell {
public:
DbCell() {}
DbCell(const T& v) : value_(v.value_) {}
DbCell(T&& v) : value_(move(v.value_)) {}
~DbCell() {}
private:
T value_;
};
struct ChapterStats {
ChapterStats() {}
};
class ChapterMap {
public:
ChapterMap() {}
ChapterMap(const ChapterMap&) = delete;
ChapterMap(ChapterMap&& cm) : the_map_(move(cm.the_map_)) {}
private:
map<string, unique_ptr<ChapterStats>> the_map_;
};
void foo() {
DbCell<ChapterMap> cm;
unique_ptr<DbCell<int>> cmp1 =
make_unique<DbCell<int>>(DbCell<int>());
unique_ptr<ChapterMap> cmp2 = make_unique<ChapterMap>(ChapterMap());
unique_ptr<DbCell<ChapterMap>> cmp3 =
unique_ptr<DbCell<ChapterMap>>(new DbCell<ChapterMap>());
// This next fails, even though I think it should be equivalent to cmp3.
cout << "> cmp4:" << endl;
unique_ptr<DbCell<ChapterMap>> cmp4 =
make_unique<DbCell<ChapterMap>>(new DbCell<ChapterMap>());
}
Run Code Online (Sandbox Code Playgroud)
没有cmp4输出是这样的(添加适当的打印语句):
Constructed ChapterMap.
Constructed DbCell.
> cmp1:
Constructed DbCell.
> cmp2:
Constructed ChapterMap.
Moved ChapterMap.
> cmp3:
Constructed ChapterMap.
Constructed DbCell.
Run Code Online (Sandbox Code Playgroud)
使用cmp4,编译器错误是这样的:
In file included from rgr.cc:6:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/memory:81:
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/unique_ptr.h:765:34: error: no matching constructor for initialization of 'DbCell<ChapterMap>'
{ return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
rgr.cc:61:9: note: in instantiation of function template specialization 'std::make_unique<DbCell<ChapterMap>, DbCell<ChapterMap> *>' requested here
make_unique<DbCell<ChapterMap>>(new DbCell<ChapterMap>());
^
rgr.cc:18:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'DbCell<ChapterMap> *' to 'const DbCell<ChapterMap>' for 1st argument; dereference the argument with *
class DbCell {
^
rgr.cc:21:5: note: candidate constructor not viable: no known conversion from 'DbCell<ChapterMap> *' to 'const ChapterMap' for 1st argument
DbCell(const T& v) : value_(v.value_) {
^
rgr.cc:24:5: note: candidate constructor not viable: no known conversion from 'DbCell<ChapterMap> *' to 'ChapterMap' for 1st argument
DbCell(T&& v) : value_(move(v.value_)) { cout << "Moved DbCell." << endl; }
^
rgr.cc:20:5: note: candidate constructor not viable: requires 0 arguments, but 1 was provided
DbCell() { cout << "Constructed DbCell." << endl; }
^
1 error generated.
Run Code Online (Sandbox Code Playgroud)
令我感到困惑的部分之一是编译器抱怨隐式删除的DbCell<ChapterMap>复制构造函数,但我已经定义了一个(我不想要,但仅作为示例)。
这两个并不相同:
make_unique<T>(T());
unique_ptr<T>(new T());
Run Code Online (Sandbox Code Playgroud)
这两个是相同的:
make_unique<T>();
unique_ptr<T>(new T());
Run Code Online (Sandbox Code Playgroud)
在第一个中,您有一个额外的移动/复制 ctor 参与了make_unique<T>.