int n=10的sizeof 为什么是四_为什么建议你用nullptr而不是NULL

前言

在C语言中,我们常常用NULL作为指针变量的初始值,而在C++中,却不建议你这么做。

NULL是什么

在《NULL,0,'0',"0","0"的区别》一文中,我们已经知道了在C中NULL是什么,在C的头文件中,通常定义如下:

#define NULL ((void*)0)

但是在C++中,它是这样定义的:

#define NULL 0

或者你可以在stddef.h看到完整的这段:

#undef NULL
#if defined(__cplusplus)
#define NULL 0
#else
#define NULL ((void *)0)
#endif

也就是说,在C++中,NULL不过也是0罢了,把它当成空指针只是一个无可奈何的选择罢了。

那么为什么在C++和C中不一样呢?因为C++中不能将void *类型的指针隐式转换成其他指针类型,从下面的例子可以看出来:

//null.cpp
#include<iostream>
int main(void)
{
    char p[] = "12345";
    int *a = (void*)p;
    return 0;
}

编译:

$ g+ -o null null.cpp
null.cpp: In function 'int main()':
null.cpp:5:17: error: invalid conversion from 'void*' to 'int*' [-fpermissive]
  int *a = (void*)p;

所以不能将NULL定义为(void*)0。

nullptr

nullptr并非整型类别,甚至也不是指针类型,但是能转换成任意指针类型。nullptr的实际类型是std:nullptr_t。

来源:公众号【编程珠玑】, https://www. yanbinghu.com

为什么该使用nullptr

回到最开始的问题,为什么作为指针的语义,我们应该使用nullptr,而不是NULL。
请看下面的代码:

//来源:公众号【编程珠玑】,https://www.yanbinghu.com
//test.cpp
#include<iostream>
using namespace std;
void test(void *p)
{
    cout<<"p is pointer "<<p<<endl;
}
void test(int num)
{
    cout<<"num is int "<<num<<endl;
}
int main(void)
{

    test(NULL);
    return 0;
}

编译:

$ g++ -o test test.cpp
main.cpp: In function ‘int main()’:
main.cpp:16:14: error: call of overloaded ‘test(NULL)’ is ambiguous
     test(NULL);

很不幸,编译报错了,提示我们有二义性,按照《重载函数匹配规则》,两个都可以匹配,因此最终报错。

但是如果我们使用nullptr却不会:

test(nullptr);

除了这点之外,在C++模板中它还有更好的表现。
看下面的代码:

//来源:公众号【编程珠玑】,https://www.yanbinghu.com
#include<iostream>
using namespace std;
template<typename Type1,typename ptrType>
void test(Type1 fun,ptrType ptr)
{
    /*do something*/
    fun(ptr);
    return;
}
void fun(int *val)
{
    cout<<"fun"<<endl;
}
int main(void)
{
    test(fun,NULL);
    return 0;
}

编译报错了:

main.cpp:8:8: error: invalid conversion from ‘long int’ to ‘int*’ [-fpermissive]
     fun(ptr);

很显然NULL被推导为long int,而不是空指针,因而导致函数类型不匹配而报错。

但是如果我们用nullptr就不会有上面的问题。

总结

如果你想表示空指针,那么使用nullptr,而不是NULL。

注:nullptr在C++ 11中才出现。

原文最新地址:https://www.yanbinghu.com/2019/08/25/36794.html

微信公众号【编程珠玑】:专注但不限于分享计算机编程基础,Linux,C语言,C++,数据结构与算法,工具,资源等编程相关[原创]技术文章。

deeac332493ab729298d9c4867fb61db.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include "mainwindow.h" #include <QApplication> #include <windows.h> #include <wtsapi32.h> #pragma comment(lib, "Wtsapi32.lib") int main(int argc, char *argv[]) { QApplication a(argc, argv); HANDLE hToken = NULL; DWORD dwSessionId = WTSGetActiveConsoleSessionId(); if (!WTSQueryUserToken(dwSessionId, &hToken)) { QMessageBox::warning(nullptr, QStringLiteral("错误"), QStringLiteral("获取用户令牌失败!")); return -1; } HANDLE mutex = ::CreateMutex(Q_NULLPTR,true,(LPCWSTR)qApp->applicationName().toStdWString().c_str()); if(GetLastError() == ERROR_ALREADY_EXISTS) { QMessageBox waringBox(QMessageBox::Warning,QStringLiteral("警告"),QStringLiteral("程序[文本数据同步客户端]只能运行一个!")); waringBox.setButtonText(QMessageBox::Ok,QStringLiteral("确定")); waringBox.setStandardButtons(QMessageBox::Ok); waringBox.exec(); ::CloseHandle(mutex); return 0; } else { ::ReleaseMutex(mutex); } STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.lpDesktop = (LPWSTR)L"winsta0\\default"; PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi)); if (!CreateProcessAsUser(hToken, NULL, (LPWSTR)qApp->applicationFilePath().toStdWString().data(), NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) { QMessageBox::warning(nullptr, QStringLiteral("错误"), QStringLiteral("创建进程失败!")); CloseHandle(hToken); return -1; } CloseHandle(hToken); MainWindow w; w.show(); return a.exec(); } 以上是限制程序在windows Server2016系统中多个用户界面也只能运行一个程序的QT C++代码,但是会出现以下BUG: 在还未有程序运行时,运行第一个也会直接提示 "获取用户令牌失败!",程序直接关闭,请帮我修复后给我完整代码
最新发布
05-30

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值