所以我有一个简单的功能以及一些文档:
/**
* @param[out] dest is overwritten by the second argument
* @param[in] src is value to overwrite the first argument with
*/
void Copy(int &dest, int src) { dest = src; }
可能不是很有用,但很明显它dest
是输出。但是,使用指针对我来说,这条线变得模糊了:
void Copy(int *dest, int src) { *dest = src; }
应该dest
还是输出?指针的值不会被修改,只有指针指向的内存中的值会被修改。但是我仍然会说是的。继续:
void Write(FILE *fw, int src) { fwrite(&src, sizeof(src), 1, fw); }
现在这对我来说确实fw
是个问题,尽管在逻辑上它是输出,但我仍将其标记为输入,并且FILE
结构的内容也会在此过程中被修改(但对我而言这是相当不透明的)。
另一方面:
void Open(FILE &*fw, const char *filename) { fw = fopen(filename, "w"); }
显然是输出。所述FILE
手柄由函数初始化,指针的值被重写。
将参数标记为输出是否有良好的经验法则或推理依据?
我什至不希望[in,out]
像C ++那样进入参数,这些基本上是所有[out]
参数(例如,如果将输出通过传递std::vector
,该函数需要获取一个实例作为输入,并且输出甚至可以重用存储)。
关于是否甚至应使用输出参数的意见不一,更不用说应如何记录它们了。不过,它们是常用的,您的问题是有效的。
参数是否应标记为[in]
,[out]
或[in,out]
取决于参数的用途。
通常,输出参数的目的是在单个返回值不足时允许被调用函数将其他信息传递给调用函数。该“附加信息”通过调用函数提供的参考参数传递。可以使用C ++参考运算符(&
)或通过指针提供参考参数,该指针是稍有不同的车辆,但结果相同。
因此,如果参数的目的是允许被调用函数向调用函数提供信息,则应在文档中将其标识为输出。
如果通过参数向函数提供文件句柄或文件名,即使该函数旨在写入文件,也将其视为输入参数。这是因为
函数未通过参数将信息传递回调用例程
写入文件被认为是该功能的副作用。
如果参考参数用于双向传递信息,则应将其记录为[in,out]
。
此外
在记录功能时,请将功能视为提供给调用方的服务。文档的读者是程序员编写将调用您的函数的代码。好像您(函数的编写者)没有意识到调用代码的上下文或特定内容一样,编写文档。本文档的目的是一般性地描述该功能的作用,并详细说明如何使用该功能。
因此,如果函数的设计者打算将dest
其用作输出,则应将其标记为输出。您还应该考虑调用者对通过该输出提供的数据不感兴趣的情况。通常,这由调用者提供,该指针提供空指针作为该参数的参数来指示。在向写入任何数据之前*dest
,您的函数应进行测试以确保dest
不为null。参数的文档dest
应声明,如果dest
为空指针,则不会写入任何数据。
使用const作为输入指针参数
另外,如果指针参数仅用于输入,则应使用const
关键字修改该参数,如下所示:
void Copy(int *dest, const int *src) { *dest = *src; }
这具有以下好处:
如果该函数的程序员错误地尝试执行此操作,它将阻止该Copy
函数写入该*src
位置。Copy
它告知并确保程序员编写调用Copy
该src
缓冲区的代码,以防止其缓冲区被修改而安全Copy
如果您始终一致地使用const
:,则它是自记录的:被标记的指针参数const
显然仅const
用于输入,而未标记的指针参数很可能用于输出。
也可以看看
输出参数(维基百科)
M. Reddy,C ++ API设计,Morgan Kaufmann,2011年。ISBN978-0123850034。