C++指针的引用是否为空?
给定以下代码:C++指针的引用是否为空?,c++,class,pointers,generics,reference,C++,Class,Pointers,Generics,Reference,给定以下代码: template<class S, class T> class node { public: S key; T value; node<S, T> *right_node, *left_node, *parent_node, *nearest_right_node, *nearest_left_node; int height; public: template<typename, typename>
template<class S, class T>
class node {
public:
S key;
T value;
node<S, T> *right_node, *left_node, *parent_node, *nearest_right_node, *nearest_left_node;
int height;
public:
template<typename, typename> friend
class avl_tree;
node() = default;
node(const S *key, const T *value, node<S, T> *right_node = nullptr, node<S, T> *left_node = nullptr,
node<S, T> *parent_node = nullptr, node<S, T> *nearest_right_node = nullptr,
node<S, T> *nearest_left_node = nullptr) : key(*key),
value(*value),
right_node(right_node),
left_node(left_node),
parent_node(parent_node),
nearest_right_node(nearest_right_node),
nearest_left_node(nearest_left_node),
height(0) {
}
~node() = default;
};
我可以调用update\u xnull\u ptr吗?代码中的问题归结为:
void foo(int* x) {
int y = *x;
}
将nullptr传递给foo将导致未定义的行为,因为您不应取消对nullptr的引用
使用引用是可能的,但不会改变这一事实:
void bar(int*& x) {
int y = *x;
}
这是通过引用传递指针
int a;
int* p = &a;
bar(p);
现在,条中的x是指向a的指针的引用。但是,您不能将空指针传递给bar,因为bar正在取消对指针的引用。某些恶意代码可能会执行以下操作:
int* p = nullptr;
bar(p); // DO NOT DO THIS !!!
然后int y=*x;将调用未定义的行为
如果函数希望始终获取有效对象,则应通过引用获取该对象:
void foo_bar(int& x) {
int y = x; // no danger, all fine
}
引用不能引用任何内容。必须对其进行初始化:
int& x; // ERROR !
int y;
int& z = y; // OK, z refers to y
另一方面,指针并不总是指向有效的指针对象:
int* p; // not initialized, no (big) problem
p = nullptr; // still not pointing to an int
int q;
p = &q; // now p points to an int
引用不能引用nothing,这就是为什么当nothing不是有效参数时,您应该更喜欢引用而不是指针。在您的情况下,您总是需要*值才有效,因此值总是必须指向S,您应该使用引用来避免上述问题
关于您的更新:
我可以调用update\u xnull\u ptr吗
不,你不能。nullptr不是int。对int的引用总是引用int。代码中的问题归结为:
void foo(int* x) {
int y = *x;
}
将nullptr传递给foo将导致未定义的行为,因为您不应取消对nullptr的引用
使用引用是可能的,但不会改变这一事实:
void bar(int*& x) {
int y = *x;
}
这是通过引用传递指针
int a;
int* p = &a;
bar(p);
现在,条中的x是指向a的指针的引用。但是,您不能将空指针传递给bar,因为bar正在取消对指针的引用。某些恶意代码可能会执行以下操作:
int* p = nullptr;
bar(p); // DO NOT DO THIS !!!
然后int y=*x;将调用未定义的行为
如果函数希望始终获取有效对象,则应通过引用获取该对象:
void foo_bar(int& x) {
int y = x; // no danger, all fine
}
引用不能引用任何内容。必须对其进行初始化:
int& x; // ERROR !
int y;
int& z = y; // OK, z refers to y
另一方面,指针并不总是指向有效的指针对象:
int* p; // not initialized, no (big) problem
p = nullptr; // still not pointing to an int
int q;
p = &q; // now p points to an int
引用不能引用nothing,这就是为什么当nothing不是有效参数时,您应该更喜欢引用而不是指针。在您的情况下,您总是需要*值才有效,因此值总是必须指向S,您应该使用引用来避免上述问题
关于您的更新:
我可以调用update\u xnull\u ptr吗
不,你不能。nullptr不是int。对int的引用始终引用int。您的节点类具有成员的key和T值,以及构造函数参数const S*key和const T*value,它们分别使用key*key和value*value初始化成员,将输入值复制到成员中
如果将nullptr传递给任一参数,则代码在取消引用nullptr时具有未定义的行为
没有理由让参数成为指针。它们应通过值传入:
样板
类节点{
公众:
S键;
T值;
...
公众:
...
节点键,T值,…:键键,值,…{}
//或者:nodeS key,T value,…:keystd::movekey,valuestd::movevalue,…{}
...
};
或通过常量引用:
void foo_bar(int& x) {
int y = x; // no danger, all fine
}
样板
类节点{
公众:
S键;
T值;
...
公众:
...
nodeconst S&key,const T&value,…:keykey,valuevalue,…{}
...
};
或通过右值引用:
void foo_bar(int& x) {
int y = x; // no danger, all fine
}
样板
类节点{
公众:
S键;
T值;
...
公众:
...
节点&&key,T&&value,…:keystd::movekey,valuestd::movevalue,…{}
...
};
如果S或T被定义为指针类型,则可以传入nullptr作为要分配给键/值成员的值,例如:
node*n=新的node1,nullptr;
t型;
节点*n=新节点1,&t;
但如果S和T不是指针类型,则不应将其作为指针传入:
t型;
节点*n=新节点1,t;
t型;
node*n=新node1,std::movet;
node*n=新节点1,类型{};
节点类具有成员的key和T值,以及构造函数参数const S*key和const T*value,它们分别使用key*key和value*value初始化成员,这将把输入值复制到成员中
如果将nullptr传递给任一参数,则代码在取消引用nullptr时具有未定义的行为
没有理由让参数成为指针。它们应通过值传入:
样板
类节点{
公众:
S键;
T值;
...
公众:
...
节点键,T值,…:键键,值,…{}
//或者:nodeS key,T value,…:keystd::movekey,valuestd::movevalue,…{}
...
};
或通过常量引用:
void foo_bar(int& x) {
int y = x; // no danger, all fine
}
样板
类节点{
公众:
S键;
T值;
...
公众:
...
nodeconst S&key,const T&value,…:keykey,valuevalue,…{}
...
};
或通过右值引用:
void foo_bar(int& x) {
int y = x; // no danger, all fine
}
样板
类节点{
公众:
S键;
T值;
...
公众:
...
节点和键,T&
&价值,…:keystd::movekey,valuestd::movevalue。。。{ }
...
};
如果S或T被定义为指针类型,则可以传入nullptr作为要分配给键/值成员的值,例如:
node*n=新的node1,nullptr;
t型;
节点*n=新节点1,&t;
但如果S和T不是指针类型,则不应将其作为指针传入:
t型;
节点*n=新节点1,t;
t型;
node*n=新node1,std::movet;
node*n=新节点1,类型{};
现在传递到构造函数中的键和值指针不能为null。如果是的话,你无论如何都会取消引用它们,并得到未定义的行为。你知道引用和指针之间的区别吗?这不是语言的一个模糊的角落,它的肉和土豆。我认为你可以从一个.key*键中获益。这个键总是错误的,没有if或but。更新是无效的。它不会编译。你不能以任何方式、形状或形式使用它。@n.“代词是m。你为什么说它总是错的?除非参数键是nullptr,否则它是ok ish。从代码无法通过审查的意义上讲是错误的,我同意您现在传递到构造函数中的键和值指针不能为null。如果是的话,你无论如何都会取消引用它们,并得到未定义的行为。你知道引用和指针之间的区别吗?这不是语言的一个模糊的角落,它的肉和土豆。我认为你可以从一个.key*键中获益。这个键总是错误的,没有if或but。更新是无效的。它不会编译。你不能以任何方式、形状或形式使用它。@n.“代词是m。你为什么说它总是错的?除非参数键是nullptr,否则它是ok ish。从某种意义上说,代码不会通过审查是错误的,我确实同意,谢谢,但这不是我的意思,我会的explain@whiteforce看到了吗?那么为什么在我的最后一个问题中,你和另一个家伙告诉我改变c'tor指向引用的指针?如果钥匙可以打开,那就没有意义了null@whiteforce这实际上是答案。看看barint*&x。原则上,您可以向它传递一个nullptr,然后x是对nullptr的引用,但只要在int y=*x行中取消对它的引用,它就会爆炸;这基本上就是你生活中发生的事情constructor@whiteforce谢谢,但这不是我的意思,我会的explain@whiteforce看到了吗?那么为什么在我的最后一个问题中,你和另一个家伙告诉我改变c'tor指向引用的指针?如果钥匙可以打开,那就没有意义了null@whiteforce这实际上是答案。看看barint*&x。原则上,您可以向它传递一个nullptr,然后x是对nullptr的引用,但只要在int y=*x行中取消对它的引用,它就会爆炸;这基本上就是你生活中发生的事情constructor@whiteforce参见编辑