将空指针传递给函数时确保编译错误
Ensuring compilation error while passing null pointer to a function
假设我有一个接收指针的函数。
int functionA(int* a, int* b)
{
...
}
我可以在 functionA 中添加 null 检查。有没有一种方法可以确保每当 nullptr
作为参数传递时在编译时发生错误。
Is there a way that I can ensure that an error occurs on the compile time whenever nullptr is passed as a parameter.
如果您具体指的是 nullptr
关键字,那么有点。您可以提供在这种情况下会选择的重载,并将它们定义为删除。只要您不通过强制转换明确绕过重载,这就有效。
int functionA(int*, std::nullptr_t) = delete;
int functionA(std::nullptr_t, int*) = delete;
// ...
functionA(&i, &j) // OK
functionA(nullptr, &i); // error
functionA(&i, nullptr); // error
functionA(nullptr, nullptr); // error
or NULL
除了之前的重载之外,这还需要为整数添加重载:
int functionA(int*, int) = delete;
int functionA(int, int*) = delete;
// ...
functionA(NULL, &i); // error
functionA(&i, NULL); // error
functionA(NULL, NULL); // error
如果你指的是任何具有空值的指针,那么这是不可能的,因为函数参数的值通常无法在编译时获知。
如果您的目标是不使用指针作为迭代器,那么传递引用会更安全、更方便。
经过一个小时的 Google 搜索,我设法找到了实现此目的的方法。
如果你真的很想做编译时检查,这就是你可以实现的方法。
#include <iostream>
#include <cstdlib>
template<typename T, T* N>
static void ValidatePtr() {
std::static_assert(N != nullptr);
}
int main() {
constexpr int* ptr = nullptr;
ValidatePtr<int, ptr>();
std::cout << "Test" << std::endl;
}
快速总结:
如果您需要验证函数的 compile-time 指针,则必须确保它们是常量表达式。该方法实际上需要一个常量表达式才能编译。这确保了唯一传递的指针必须在编译时确定。您不能使用 &variable
引用其他变量的地址,因为它会引发编译器错误,因此必须专门输入 constexpr int* ptr = nullptr;
或 constexpr int* ptr = (int*)0xFFFFFFFF
.
但是,如果您想要检查动态变量,则需要在运行时进行检查,因为没有使用 constexpr
来确定地址的方法。
除了内存实用程序之外,我真的看不到它的用途。
我强烈建议对 nullptr
进行运行时检查,如果您认为有必要,请使用普通的 assert
调用而不是 static_assert
或简单地引发异常使用 throw
.
这里正确的做法是使用引用。
int functionA(int& a, int& b);
关于引用的心智模型是:这些是永远不应该代表 nullptr 的指针。
假设我有一个接收指针的函数。
int functionA(int* a, int* b)
{
...
}
我可以在 functionA 中添加 null 检查。有没有一种方法可以确保每当 nullptr
作为参数传递时在编译时发生错误。
Is there a way that I can ensure that an error occurs on the compile time whenever nullptr is passed as a parameter.
如果您具体指的是 nullptr
关键字,那么有点。您可以提供在这种情况下会选择的重载,并将它们定义为删除。只要您不通过强制转换明确绕过重载,这就有效。
int functionA(int*, std::nullptr_t) = delete;
int functionA(std::nullptr_t, int*) = delete;
// ...
functionA(&i, &j) // OK
functionA(nullptr, &i); // error
functionA(&i, nullptr); // error
functionA(nullptr, nullptr); // error
or
NULL
除了之前的重载之外,这还需要为整数添加重载:
int functionA(int*, int) = delete;
int functionA(int, int*) = delete;
// ...
functionA(NULL, &i); // error
functionA(&i, NULL); // error
functionA(NULL, NULL); // error
如果你指的是任何具有空值的指针,那么这是不可能的,因为函数参数的值通常无法在编译时获知。
如果您的目标是不使用指针作为迭代器,那么传递引用会更安全、更方便。
经过一个小时的 Google 搜索,我设法找到了实现此目的的方法。 如果你真的很想做编译时检查,这就是你可以实现的方法。
#include <iostream>
#include <cstdlib>
template<typename T, T* N>
static void ValidatePtr() {
std::static_assert(N != nullptr);
}
int main() {
constexpr int* ptr = nullptr;
ValidatePtr<int, ptr>();
std::cout << "Test" << std::endl;
}
快速总结:
如果您需要验证函数的 compile-time 指针,则必须确保它们是常量表达式。该方法实际上需要一个常量表达式才能编译。这确保了唯一传递的指针必须在编译时确定。您不能使用 &variable
引用其他变量的地址,因为它会引发编译器错误,因此必须专门输入 constexpr int* ptr = nullptr;
或 constexpr int* ptr = (int*)0xFFFFFFFF
.
但是,如果您想要检查动态变量,则需要在运行时进行检查,因为没有使用 constexpr
来确定地址的方法。
除了内存实用程序之外,我真的看不到它的用途。
我强烈建议对 nullptr
进行运行时检查,如果您认为有必要,请使用普通的 assert
调用而不是 static_assert
或简单地引发异常使用 throw
.
这里正确的做法是使用引用。
int functionA(int& a, int& b);
关于引用的心智模型是:这些是永远不应该代表 nullptr 的指针。