如果我需要在c++中区分0和NULL

What if I need to differentiate 0 from NULL in C++?

本文关键字:NULL 中区 c++ 如果      更新时间:2023-10-16

**请不要批评代码本身的目的。出自Pat Morin的《开放数据结构》一书。不是我的首选,它是指定的阅读/练习。我只是想知道是否有一种求导的方法,或者一种更好的方法。教科书——> http://opendatastructures.org/ods-cpp/* *

**另一个注意事项:我来自Java,这将是允许的。我的代码仍然可以编译,它只是"修复"它**

我很惊讶以前没有出现过这样的问题,因为这似乎是一个如此简单的问题。也许它被埋了,或者我用的术语不对。

我有一个for循环遍历vector中的数据。我需要返回被搜索的值,如果它被找到。如果找不到怎么办?这是我的代码。

int find(int x) {
    for(int i=0;i<bag.size();i++){
        // if x is equal to data, return data
        if (bag[i]==x){
            return bag[i]; // ends loop as soon as one instance is found
        }
    }
    // if we made it this far, no match was found.
    return NULL;
}

相当简单。假设0是我可能需要记录和搜索的有效值之一。事实上,它实际上返回0,而不是"NULL"。研究表明这是一回事。我该如何指定或区分?除了返回一个不会在程序中出现的晦涩数字(比如-1或-9999999)。例如,搜索您的帐户余额。没有数字是不可能的。

为什么要从查找函数返回您正在搜索的值?你已经知道了这个值,它就是你传递给函数的值。返回找到的元素的位置,因为这个信息更有用。当没有找到该值时,您可以返回一个特殊位置,如-1。或者您可以遵循标准库的模型并返回end迭代器,该迭代器表示距离范围结束后1的位置。

可以用几种方法编写这个函数

bool find( int x ) 
{
    std::vector<int>::size_type i = 0;
    while (  i < bag.size() && bag[i] != x ) i++;
    return i != bag.size();
}

std::vector<int>::size_type find( int x ) 
{
    std::vector<int>::size_type i = 0;
    while (  i < bag.size() && bag[i] != x ) i++;
    return i;
}

#include <algorithm>
//...
std::vector<int>::iterator find( int x ) 
{
    return std::find( beg.begin(), bag.end(), x );
}

并以下列方式使用相应的函数

if ( find( x ) ) { /*...*/ }
if ( find( x ) != bag.size() ) { /*...*/ }
if ( find( x ) != bag.end() ) { /*...*/ }

关于你在文章标题中提出的一般性问题

如果我需要在c++中区分0和NULL怎么办?

那么你需要使用nullptr而不是NULL来区分0和NULL。:)

#define XOR_MSB(x) (x^0x80000000)
int find(bool found) {
    return found ? XOR_MSB(0) : NULL;
}
int main()
{
    int value = find(false);
    if (value == NULL) printf("not foundn");
    else printf("%dn", XOR_MSB(value));
    value = find(true);
    if (value == NULL) printf("not foundn");
    else printf("%dn", XOR_MSB(value));
    return 0;
}

你说的是一个邪恶的做法,来自Java和c#开发人员,你可以返回null作为无效的结果。

在c++中是做不到的。Java和c#几乎在堆上声明所有东西,并且访问对象总是由引用完成。这意味着你总是从函数返回一个指针,并且你总是可以返回一个null作为返回值。

在c++中,当函数不返回指针时,

是不可能的。例如,函数std::string returnString()不能返回null作为返回值。

多了,不应该返回null作为无效输出。这在很多层面上都是错误的,即使在c#和Java中也是如此!如果函数失败,只需抛出异常,或者将返回值作为引用参数传递,并使函数返回true或false。

您还可以找到不太激进的解决方案,如返回-1(如javascript中的indexOf())或返回std::string::nposstd::vector:end之类的东西,它们更符合c++ STL。

这就是boost::optional<T>的作用。实际上,这种类型表示"可能有T,但可能没有T"。用户可以检查是否有T。理想情况下,您将不依赖于T的任何特殊值,而是使用optional<T>optional<T>是完全通用的,可以适用于任何T你可能需要使用,它不依赖于T的一些特殊值或状态。

boost::optional<int> find(int x) {
    for(int i=0;i<bag.size();i++){
        // if x is equal to data, return data
        if (bag[i]==x){
            return bag[i]; // ends loop as soon as one instance is found
        }
    }
    // if we made it this far, no match was found.
    return boost::none;    
}
int main() {
    if (auto opt = find(5))
        std::cout << *opt;
}

永远不要使用NULL,这是一件可怕的事情。始终使用nullptr,这实际上是更安全的,它更安全的原因之一是因为你的错误代码将无法编译。