相关功能的API参考:RmStartSession。
代码:
#include <Windows.h>
#include <RestartManager.h>
/*
DWORD WINAPI
RmStartSession(
_Out_ DWORD *pSessionHandle,
_Reserved_ DWORD dwSessionFlags,
_Out_writes_(CCH_RM_SESSION_KEY + 1) WCHAR strSessionKey[]);
*/
int main(int /*argc*/, char** /*argv*/)
{
WCHAR sessionKey[CCH_RM_SESSION_KEY + 1];
// 1.
DWORD *sessionOne = nullptr;
auto returnCodeOne = RmStartSession(sessionOne, NULL, sessionKey); // = 160 ERROR_BAD_ARGUMENTS
// 2.
DWORD sessionTwo = 0xFFFFFFF;
DWORD *pSessionHandleTwo = &sessionTwo;
auto returnCodeTwo = RmStartSession(pSessionHandleTwo, NULL, sessionKey); // = 0 ERROR_SUCCESS
// 3.
DWORD sessionThree = 0xFFFFFFF;
auto returnCodeThree = RmStartSession(&sessionThree, NULL, sessionKey); // = 0 ERROR_SUCCESS
return 0;
}
我花了一些时间才意识到为什么1.
给了我一个BAD_ARGUMENTS
错误,因为上面编译好的所有变种都是合法的语言结构。
问题是该函数实际上需要一个指向有效对象的指针,并且只是使用该指针来修改对象,而不是修改指针本身。因此,如果指针是nullptr
,那么没有要修改的对象,该函数本身不会分配对象
(如果我的理解错误,请纠正我)
话虽如此,为什么定义的函数不能请求引用DWORD
以明确它不能为空,是否有特定的理由在这里使用指针?
我错过了什么?
答案 0 :(得分:1)
这个问题有两个答案:
这是一个C api,因此API编写者无法使用引用。
有一种想法认为使用输出值参数的引用是错误的API设计,并且应始终使用指针,即使这意味着传递nullptr
将是一场灾难。
这个想法是基于参考的输出参数在呼叫站点真的很混乱。请查看以下代码:
void foo() {
my_struct val;
bar(val);
}
void foo_alt() {
my_struct val;
bar_alt(&val);
}
乍一看,人们不希望bar
在第一个例子中修改val
,但有人会在第二个例子中怀疑它。
通过仅查看调用站点来了解函数的作用是自我记录代码的基础,而可变引用通常会破坏它(除非它在函数名称中非常清楚)。