Fiz*_*erd 2 c++ constructor c++11
解决了!见下文
所以,我正在尝试通过做一些简单的数据结构并使用它们来学习C++ 11.我使用原始指针做了类似于以下BST示例的操作new,delete并且它工作正常.然后我想以更加泄密的方式做到这一点.
// tree.cpp
//
//
#include <iostream>
#include <memory>
/* DECLARATIONS */
template <typename T>
struct Tree {
// members
T data;
std::unique_ptr<Tree<T> > left;
std::unique_ptr<Tree<T> > right;
// methods
Tree (T arg);
~Tree () = default;
void insert (Tree<T> child);
void insert (T arg);
void print (void);
};
template <typename T>
Tree<T>::Tree (T arg) {
data = arg;
left = nullptr;
right = nullptr;
}
template <typename T>
void Tree<T>::insert (Tree<T> child) {
if (child.data < data) {
if (left) {
left->insert(child);
} else {
left = &child;
}
} else {
if (right) {
right->insert(child);
} else {
right = &child;
}
}
}
template <typename T>
void Tree<T>::insert (T arg) {
Tree<T> child (arg);
this->insert(child);
}
template <typename T>
void Tree<T>::print (void) {
if (left) {
left->print();
}
std::cout << data;
if (right) {
right->print();
}
}
int main (void) {
Tree<int> root (0);
root.insert(3);
root.insert(-3);
root.insert(-2);
root.insert(2);
root.insert(11);
root.print();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,我并没有理解我从clang ++中得到的错误.
$ clang++ -std=c++11 tree.cpp
tree_new.cpp:50:16: error: call to deleted constructor of 'Tree<int>'
this->insert(child);
^~~~~
tree_new.cpp:66:8: note: in instantiation of member function 'Tree<int>::insert' requested here
root.insert(3);
^
tree_new.cpp:10:8: note: function has been explicitly marked deleted here
struct Tree {
^
tree_new.cpp:18:24: note: passing argument to parameter 'child' here
void insert (Tree<T> child);
^
tree_new.cpp:34:20: error: call to deleted constructor of 'Tree<int>'
left->insert(child);
^~~~~
tree_new.cpp:50:9: note: in instantiation of member function 'Tree<int>::insert'requested here
this->insert(child);
^
tree_new.cpp:66:8: note: in instantiation of member function 'Tree<int>::insert' requested here
root.insert(3);
^
tree_new.cpp:10:8: note: function has been explicitly marked deleted here
struct Tree {
^
tree_new.cpp:18:24: note: passing argument to parameter 'child' here
void insert (Tree<T> child);
^
2 errors generated.
Run Code Online (Sandbox Code Playgroud)
为什么说我在声明时明确删除了构造函数struct?我甚至明确定义了一个构造函数!此外,任何关于范围/所有权失败的意见将不胜感激.我很确定这不会像我做的那样有效.
解
来自MSDN的以下链接阐明了如何使用unique_ptrs.
特别感谢BatchyX对问题的初步解释(unique_ptr隐式地使用一个成员(虽然编译器说"明确"......)删除了类的复制构造函数),并注意到Tree确实仍然是可移动的.
MSDN文章中提到的东西是std::move()返回其参数的右值.
这是适当修改的代码(不包括明显修改的声明).请注意,使用std :: forward可能仍然可以进行一些优化,但这至少可以编译并正确运行.
template <typename T>
void Tree<T>::insert (std::unique_ptr<Tree<T> >&& pchild) {
if (pchild->data < data) {
if (left) {
// recurse, but must match on the rvalue signature
left->insert(std::move(pchild));
} else {
// invokes the move constructor for left instead of its copy constructor
left = std::move(pchild);
}
} else {
if (right) {
right->insert(std::move(pchild));
} else {
right = std::move(pchild);
}
}
}
template <typename T>
void Tree<T>::insert (T arg) {
// what is inside the insert(...) is an rvalue.
this->insert(std::unique_ptr<Tree<T> >(new Tree<T> (arg)));
}
Run Code Online (Sandbox Code Playgroud)
std::unique_ptr不可复制,任何包含a的类unique_ptr也不可复制,这意味着struct Tree不可复制.论点:
void Tree<T>::insert (Tree<T> child) {
Run Code Online (Sandbox Code Playgroud)
正在以价值来论证.和:
template <typename T>
void Tree<T>::insert (T arg) {
Tree<T> child (arg);
this->insert(child);
}
Run Code Online (Sandbox Code Playgroud)
需要复制构造函数.要纠正这个问题,请使其struct Tree可移动.
注意Tree是不是可移动的(相对于BatchyX的评论),由于存在:
~Tree () = default;
Run Code Online (Sandbox Code Playgroud)
这是一个用户声明的析构函数,来自12.8节复制和移动 c ++ 11标准的类对象(第9点)(草案n3337):
如果类X的定义没有显式地声明一个移动构造函数,那么当且仅当一个移动构造函数被隐式声明为默认值时
- X没有用户声明的复制构造函数,
- X没有用户声明的复制赋值运算符,
- X没有用户声明的移动赋值运算符,
- X没有用户声明的析构函数,和
- 移动构造函数不会被隐式定义为已删除.
(我不确定移动成员的隐含生成并且问这个问题是肯定的).为了使其可移动:
| 归档时间: |
|
| 查看次数: |
757 次 |
| 最近记录: |