c++:成员函数中的"this == nullptr"安全吗?
c++: Is `this == nullptr` safe in member functions?
要计算二叉树的高度,使用height(left)+height(right)+1
并将不存在的节点的高度定义为-1。因此,如果 left 或 right 为 null,则公式无需显式指定这些情况即可工作。
我在 C++ 年实现了这个想法,并确保成员函数在this == nullptr
时不会访问成员变量。我的实现是成功的并且有效(至少在我的 Linux 机器上(。
我想找出这种方法可能具有什么样的实际缺点,以及标准是否对此有所规定。所以,这是我的问题。
#include <algorithm>
#include <iostream>
struct Node {
// default values of the child nodes are NULL
Node *left = nullptr;
Node *right = nullptr;
// store some value
int v;
int get_height() const __attribute__ ((optimize(0))) {
if (this == nullptr)
return -1;
return std::max(left->get_height(), right->get_height()) + 1;
}
};
int main() {
Node node1, node2, node3, node4;
node2.left = &node1;
node2.right = &node3;
node3.right = &node4;
std::cout << node2.get_height() << std::endl;
return 0;
}
编辑:如果启用了优化,则代码将失败并出现分段错误。可以通过将__attribute__ ((optimize(0)))
附加到函数来解决问题。
this == nullptr
是"安全的",因为它没有任何副作用。
this == nullptr
是无用的,因为在任何具有明确定义行为的程序中,它永远不会true
。因此,允许优化器假装您编写了:
if (false)
return -1;
return std::max(left->get_height(), right->get_height()) + 1;
这与编写相同:
return std::max(left->get_height(), right->get_height()) + 1;
不安全的做法是通过 null 指针(或任何其他不指向具有活动生存期的对象的指针(调用成员函数。这种检查并不能防止这种情况,即使人们可能直觉地认为它确实如此。示例程序的行为未定义。
函数定义良好的实现示例:
int get_height() const {
int lh = left ? left->get_height() : -1;
int rh = right ? right->get_height() : -1;
return std::max(lh, rh) + 1;
}
非成员函数可能有助于避免一点点重复。
<小时 />附言一个好的编译器会警告你潜在的错误:
警告:"this"指针在定义良好的C++代码中不能为 null;可以假定比较总是计算为 false [-Wtautological-undefined-compare]
if (this == nullptr) ^~~~ ~~~~~~~
不,if (this == nullptr)
不是"安全的"。 if 语句可能为真的唯一方法是,如果您在空指针上调用了成员函数,并且这样做是未定义的行为。 这意味着支票是完全多余的,因为它在法律代码中永远不可能是真的。
this
不能nullptr
,编译器可能会优化它,因为this
为空指针是UB的结果。
类似案例:
ptr->someStaticMethod(); // if ptr is null this is an UB, even if method is static.
if(!ptr)
abort(); // May never happen, even if ptr is nullptr
如果您希望能够在尝试获取对象高度的同时处理nullptr
,则应使用非成员函数。
namespace MyApp
{
int get_height(Node const* n)
{
return ( n == nullptr ) ? -1 : n->get_height();
}
}
和使用
Node* n = ...;
...
int h = MyApp::get_height(n);
- 如何在自删除后将对象设置为nullptr
- 如何取消对nullptr的屏蔽,返回正确的对象
- C++ - "!pointer"和"pointer == nullptr"的区别?
- 将指针设置为"nullptr"并不能防止双重删除?
- 创建具有 new in 函数和"this is nullptr"异常的对象
- 为什么我的节点在我设置后被设置为 nullptr = 新节点?
- C++默认情况下,指针类型数组的元素是否保证初始化为 nullptr?
- 在 nullptr 上调用无状态类的非静态成员函数是否合法?
- 空指针常量 (nullptr)、空指针值和空成员指针值之间有什么区别?
- 哈希映射使用 nullptr c++ 初始化节点的动态数组
- wx通用目录控制错误"wxTheFileIconsTable was nullptr"
- 当设置为 const 变量时使用 nullptr
- 为什么"weak.lock()"返回"nullptr" "auto weak=std::make_shared<int>(42);"的定义?
- 检查类方法中是否(此 == nullptr)
- C++98,但叮叮当当地说使用nullptr?
- 为什么调试器引发"read access violation. this was nullptr"异常?
- 检查模板中 nullptr 的函数指针,了解任何类型的可调用对象
- 检查nullptr是否100%保护内存布局不受segfault影响
- 向unordered_map添加unique_ptr时'this was nullptr'
- 使用 nullptr 作为 std::unordered_map 的键有什么后果吗?