如何在 class 中正确使用智能指针
How to correctly use smart pointers inside of a class
我正在用 C++ 创建一个二叉树,在节点 class 内部使用智能指针时遇到一些问题。
使用普通指针时,一切正常,但使用智能指针时,它就不起作用了。我认为问题出在插入方法的这一行:
'''
binaryNode* node = this; // This is working
std::shared_ptr<binaryNode> node {this}; // This throws "double free or corruption" error
std::shared_ptr<binaryNode> node = shared_from_this (); // This throws "bad weak ptr error", I am correctly inheriting from enable_shared_from_this
'''
如何使用智能指针复制 binaryNode* node = this;
?
我什至尝试成功使用 public std::enable_shared_from_this<binaryNode>
。
感谢您的帮助!
编辑:
我会尝试更好地解释自己。这是二叉搜索树的 insert()
函数,看起来像这样(这是 .cpp 文件):
'''
#include "binarynode.h"
binaryNode::binaryNode(int value){
this->value = value;
this->right = nullptr;
this->left = nullptr;
}
void binaryNode::insert(int value){
binaryNode* node = this;
while(true){
if(value > node->value){
if(node->right != nullptr){
node = node->right;
}else{
node->right = new binaryNode(value);
break;
}
}else if(value < node->value){
if(node->left != nullptr){
node = node->left;
}else{
node->left = new binaryNode(value);
break;
}
}else{
return;
}
}
如何使用智能指针复制它?
编辑 2:
这是我的 .h 文件:
'''
#ifndef BINARYNODE_H
#define BINARYNODE_H
class binaryNode
{
public:
int value;
binaryNode(int value);
binaryNode* right;
binaryNode* left;
void insert(int value);
};
#endif // BINARYNODE_H
这是主文件:
#include <iostream>
#include "binarynode.h"
using namespace std;
void printTree(binaryNode* node){
if(node == nullptr) return;
cout << node->value << endl;
printTree(node->left);
printTree(node->right);
}
int main(){
binaryNode* bn = new binaryNode(9);
bn->insert(4);
bn->insert(20);
bn->insert(1);
bn->insert(6);
bn->insert(15);
bn->insert(170);
printTree(bn);
return 0;
}
- 您不能多次将同一个原始指针直接转换为共享指针,因为那样您将拥有多个彼此一无所知的所有者,每个所有者都认为自己可以完全控制该对象。这就是
std::shared_ptr<binaryNode> node {this}
给你双删除的原因。
- 除非至少有一个共享指针已经指向您的对象,否则您也不能使用
shared_from_this
。这就是 std::shared_ptr<binaryNode> node = shared_from_this ()
不起作用的原因。
如果您想要共享指针,请将它们全部共享。例如:
// binaryNode* bn = new binaryNode(9); <-- nope!
auto bn = std::make_shared<binaryNode>(9);
// binaryNode* node = this; <-- nope!
std::shared_ptr<binaryNode> node = shared_from_this();
虽然我不建议在这里使用共享指针。唯一指针更合适。
您不需要使用 shared_ptr<>。
实际上智能指针指向对象的 'solve' 所有权,因此当一个对象只有一个所有者时,应该使用 unique_ptr<>,当所有权共享时,shared_ptr 被使用。在你的情况下,所有权是明确的,每个节点 拥有 它的左右成员,因此 unique_ptr 可以使用。
对于树遍历问题,不要乱用智能指针,因为你不请求任何所有权,而只是查看值,因此原始指针是可以的。
所以你可能会得到这样的结果:
#include <memory>
#include <iostream>
struct binaryNode {
binaryNode(int value) : value(value) {}
void insert(int value);
int value = 0;
std::unique_ptr<binaryNode> right;
std::unique_ptr<binaryNode> left;
};
void binaryNode::insert(int value){
binaryNode* node = this;
while(true){
if(value > node->value){
if(node->right != nullptr){
node = node->right.get();
}else{
node->right = std::make_unique<binaryNode>(value);
break;
}
}else if(value < node->value){
if(node->left != nullptr){
node = node->left.get();
}else{
node->left = std::make_unique<binaryNode>(value);
break;
}
}else{
return;
}
}
}
void printTree(const binaryNode &node){
std::cout << node.value << std::endl;
if (node.left)
printTree(*node.left);
if (node.right)
printTree(*node.right);
}
int main(){
auto bn = std::make_unique<binaryNode>(9);
bn->insert(4);
bn->insert(20);
bn->insert(1);
bn->insert(6);
bn->insert(15);
bn->insert(170);
printTree(*bn);
return 0;
}
你可能会注意到打印不需要指针,它可以在引用上工作。
C++ 向量可用于支持递归数据结构。使用 smart ptr 要简单得多。基本上在您的 Node 中存储向量 children 作为成员。
#include <vector>
using std::vector;
struct Node {
Node() = default;
Node(const Node &) = delete;
Node(Node &&) = default;
vector<Node> children;
};
int main()
{
Node root;
root.children.push_back(Node());
root.children.push_back(Node());
root.children[0].children.push_back(Node());
}
我正在用 C++ 创建一个二叉树,在节点 class 内部使用智能指针时遇到一些问题。 使用普通指针时,一切正常,但使用智能指针时,它就不起作用了。我认为问题出在插入方法的这一行:
'''
binaryNode* node = this; // This is working
std::shared_ptr<binaryNode> node {this}; // This throws "double free or corruption" error
std::shared_ptr<binaryNode> node = shared_from_this (); // This throws "bad weak ptr error", I am correctly inheriting from enable_shared_from_this
'''
如何使用智能指针复制 binaryNode* node = this;
?
我什至尝试成功使用 public std::enable_shared_from_this<binaryNode>
。
感谢您的帮助!
编辑:
我会尝试更好地解释自己。这是二叉搜索树的 insert()
函数,看起来像这样(这是 .cpp 文件):
'''
#include "binarynode.h"
binaryNode::binaryNode(int value){
this->value = value;
this->right = nullptr;
this->left = nullptr;
}
void binaryNode::insert(int value){
binaryNode* node = this;
while(true){
if(value > node->value){
if(node->right != nullptr){
node = node->right;
}else{
node->right = new binaryNode(value);
break;
}
}else if(value < node->value){
if(node->left != nullptr){
node = node->left;
}else{
node->left = new binaryNode(value);
break;
}
}else{
return;
}
}
如何使用智能指针复制它?
编辑 2: 这是我的 .h 文件:
'''
#ifndef BINARYNODE_H
#define BINARYNODE_H
class binaryNode
{
public:
int value;
binaryNode(int value);
binaryNode* right;
binaryNode* left;
void insert(int value);
};
#endif // BINARYNODE_H
这是主文件:
#include <iostream>
#include "binarynode.h"
using namespace std;
void printTree(binaryNode* node){
if(node == nullptr) return;
cout << node->value << endl;
printTree(node->left);
printTree(node->right);
}
int main(){
binaryNode* bn = new binaryNode(9);
bn->insert(4);
bn->insert(20);
bn->insert(1);
bn->insert(6);
bn->insert(15);
bn->insert(170);
printTree(bn);
return 0;
}
- 您不能多次将同一个原始指针直接转换为共享指针,因为那样您将拥有多个彼此一无所知的所有者,每个所有者都认为自己可以完全控制该对象。这就是
std::shared_ptr<binaryNode> node {this}
给你双删除的原因。 - 除非至少有一个共享指针已经指向您的对象,否则您也不能使用
shared_from_this
。这就是std::shared_ptr<binaryNode> node = shared_from_this ()
不起作用的原因。
如果您想要共享指针,请将它们全部共享。例如:
// binaryNode* bn = new binaryNode(9); <-- nope!
auto bn = std::make_shared<binaryNode>(9);
// binaryNode* node = this; <-- nope!
std::shared_ptr<binaryNode> node = shared_from_this();
虽然我不建议在这里使用共享指针。唯一指针更合适。
您不需要使用 shared_ptr<>。
实际上智能指针指向对象的 'solve' 所有权,因此当一个对象只有一个所有者时,应该使用 unique_ptr<>,当所有权共享时,shared_ptr 被使用。在你的情况下,所有权是明确的,每个节点 拥有 它的左右成员,因此 unique_ptr 可以使用。
对于树遍历问题,不要乱用智能指针,因为你不请求任何所有权,而只是查看值,因此原始指针是可以的。
所以你可能会得到这样的结果:
#include <memory>
#include <iostream>
struct binaryNode {
binaryNode(int value) : value(value) {}
void insert(int value);
int value = 0;
std::unique_ptr<binaryNode> right;
std::unique_ptr<binaryNode> left;
};
void binaryNode::insert(int value){
binaryNode* node = this;
while(true){
if(value > node->value){
if(node->right != nullptr){
node = node->right.get();
}else{
node->right = std::make_unique<binaryNode>(value);
break;
}
}else if(value < node->value){
if(node->left != nullptr){
node = node->left.get();
}else{
node->left = std::make_unique<binaryNode>(value);
break;
}
}else{
return;
}
}
}
void printTree(const binaryNode &node){
std::cout << node.value << std::endl;
if (node.left)
printTree(*node.left);
if (node.right)
printTree(*node.right);
}
int main(){
auto bn = std::make_unique<binaryNode>(9);
bn->insert(4);
bn->insert(20);
bn->insert(1);
bn->insert(6);
bn->insert(15);
bn->insert(170);
printTree(*bn);
return 0;
}
你可能会注意到打印不需要指针,它可以在引用上工作。
C++ 向量可用于支持递归数据结构。使用 smart ptr 要简单得多。基本上在您的 Node 中存储向量 children 作为成员。
#include <vector>
using std::vector;
struct Node {
Node() = default;
Node(const Node &) = delete;
Node(Node &&) = default;
vector<Node> children;
};
int main()
{
Node root;
root.children.push_back(Node());
root.children.push_back(Node());
root.children[0].children.push_back(Node());
}