api函数是啥意思,有啥分类?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了api函数是啥意思,有啥分类?相关的知识,希望对你有一定的参考价值。
参考技术Aapi是应用程序编程接口。
API是一些预先定义的接口(如函数、HTTP接口),或指软件系统不同组成部分衔接的约定。用来提供应用程序与开发人员基于某软件或硬件得以访问的一组例程,而又无需访问源码,或理解内部工作机制的细节。
分类:
API函数包含在Windows系统目录下的动态连接库文件中。Windows API是一套用来控制Windows的各个部件的外观和行为的预先定义的Windows函数。
用户的每个动作都会引发一个或几个函数的运行以告诉Windows发生了什么。这在某种程度上很像Windows的天然代码。而其他的语言只是提供一种能自动而且更容易的访问API的方法。
当点击窗体上的一个按钮时,Windows会发送一个消息给窗体,VB获取这个调用并经过分析后生成一个特定事件。
以上内容参考 百度百科—API
“检查自我分配”有啥问题,它是啥意思?
【中文标题】“检查自我分配”有啥问题,它是啥意思?【英文标题】:What is wrong with "checking for self-assignment" and what does it mean?“检查自我分配”有什么问题,它是什么意思? 【发布时间】:2012-08-14 10:55:03 【问题描述】:在 Herb Sutter 的书 Exceptional C++ (1999) 中,他在第 10 项的解决方案中有一句话:
“异常不安全”和“糟糕的设计”齐头并进。如果一段代码不是异常安全的,那通常没关系,可以简单地修复。但是,如果一段代码由于其底层设计而不能成为异常安全的,那几乎总是表明其设计不佳。
示例 1:具有两种不同职责的函数很难使异常安全。
示例 2:以必须检查自赋值的方式编写的复制赋值运算符可能也不是强异常安全
他所说的“检查自我分配”是什么意思?
[查询]
Dave 和 AndreyT 准确地向我们展示了“检查自我分配”的含义。那挺好的。但问题还没有结束。为什么“检查自我分配”会损害“异常安全”(根据 Hurb Sutter 的说法)?如果调用者尝试进行自分配,则该“检查”就像没有发生分配一样工作。真的很痛吗?
[MEMO 1] 在 Herb 书中后面的第 38 条对象身份中,他解释了自我分配。
【问题讨论】:
“以这样的方式必须”这里最重要的词是:必须 【参考方案1】:在这种情况下更重要的问题是:
“这是什么意思,当你以某种方式编写函数时,需要你检查自赋值???”
回答我的反问:这意味着设计良好的赋值运算符不需要检查自赋值。将一个对象分配给自身应该可以正常工作(即具有“什么都不做”的最终效果),而不需要对自分配进行显式检查。
例如,如果我想实现一个简单的数组类
class array
// code...
int *data;
size_t n;
;
...并提出了赋值运算符的以下实现...
array &array::operator =(const array &rhs)
delete[] data;
n = rhs.n;
data = new int[n];
std::copy_n(rhs.data, n, data);
return *this;
这种实现会被认为是“糟糕的”,因为它在自分配的情况下显然会失败。
为了“修复”这个问题,开发者有两种选择;
-
他或她可以添加明确的自我分配检查
array &array::operator =(const array &rhs)
if (&rhs != this)
delete[] data;
n = rhs.n;
data = new int[n];
std::copy_n(rhs.data, n, data);
return *this;
-
或者您可以采用“无检查”方法:
array &array::operator =(const array &rhs)
size_t new_n = rhs.n;
int *new_data = new int[new_n];
std::copy_n(rhs.data, new_n, new_data);
delete[] data;
n = new_n;
data = new_data;
return *this;
从某种意义上说,后一种方法更好,因为它可以在不进行显式检查的情况下在自分配情况下正常工作。从'安全的角度'来看,这个实现远非完美,这里是为了说明处理自分配的“检查”和“无检查”方法之间的区别。后面的无检查实现可以通过众所周知的复制和交换习语来更优雅地编写。
这并不意味着您应该避免对自分配进行显式检查。从性能的角度来看,这样的检查确实有意义:执行一长串操作只是为了最终“什么都不做”是没有意义的。但在设计良好的赋值运算符中,从正确性的角度来看,这种检查是不必要的。
【讨论】:
"从性能的角度来看,这样的检查确实有意义" Rally,自赋值经常发生在你的程序中? @curiousguy:取决于程序,取决于算法。如果它允许自我分配,那就这样吧。无分支代码看起来总是比有分支代码更优雅,这意味着在这种情况下我会允许自分配发生,而不是试图在外部捕获和阻止它。 好的。我应该承认,理解“检查自我分配”语句需要一个强大的上下文。 我认为在顶部有一个if (this != &rhs) return *this;
通常会导致更容易验证为正确的功能。在您的第三种情况下,我发现自己正在检查正确性。在自我分配不是这种情况的假设下工作,通常更容易对代码进行推理。
@Aidiakapi - 你不是说如果 (this == &rhs) return *this;【参考方案2】:
来自 c++ 核心指南
Foo& Foo::operator=(const Foo& a) // OK, but there is a cost
if (this == &a) return *this;
s = a.s;
i = a.i;
return *this;
这显然是安全且有效的。但是,如果我们每百万次分配一个自我分配呢?这大约是一百万次冗余测试(但由于答案基本上总是相同的,因此计算机的分支预测器基本上每次都会猜对)。考虑:
Foo& Foo::operator=(const Foo& a) // simpler, and probably much better
s = a.s;
i = a.i;
return *this;
注意:上面的代码只适用于没有指针的类,因为有指针的类指向动态内存。请参考蚂蚁的回答。
【讨论】:
err,如果某些东西是动态分配的呢?您必须检查自我分配,然后其他答案已经明确 如果某些东西不是动态分配的怎么办?这是同一件事的不同方面。 我同意,但你应该明确表示,如果你的类中没有指针,这只是一个很好的优化。 我按照您的建议添加评论。【参考方案3】:MyClass& MyClass::operator=(const MyClass& other) // copy assignment operator
if(this != &other) // <-- self assignment check
// copy some stuff
return *this;
将一个对象分配给它自己是一个错误,但它不应该在逻辑上导致你的类实例发生变化。如果您设法设计了一个分配给自身的类会改变它,那么它的设计就很糟糕。
【讨论】:
@Mooing Duck 不要如此彻底地编辑我的答案。我什至不同意您添加的内容-这是最简单的方法,而且几乎总是次优的。有时没关系,有时则不然。写下你自己的答案。 我认为答案会更好,如果它还包含一个与坏事一起做事的好方法的样本。对不起,如果我越界了。你说得对,它是次优的,但它非常标准,因为它足够快,而且很难搞砸。如果你能提供一些关于正确分配作业的方法,我会赞成。 (不一定是复制和交换,你可以不同意我的观点) @MooingDuck 我认为几乎始终正确的方法是不明确提供复制分配操作。如果你的类设计得很好,那么默认值就是你想要的。 那应该在答案中。【参考方案4】:检查自分配的一般原因是因为您在复制新数据之前销毁了自己的数据。这种赋值运算符结构也不是强异常安全的。
作为附录,已确定自赋值对性能完全没有好处,因为每次都必须运行比较,但自赋值极为罕见,如果确实发生,这是您的程序中的逻辑错误(真的)。这意味着在整个程序过程中,这只是浪费周期。
【讨论】:
"这是您程序中的逻辑错误(真的)。" 真的,不是。 自我赋值是毫无意义的陈述。程序员永远不会故意编写无意义的语句;因此总是出错。 不,自分配应该没有效果。这不是毫无意义的。 没有效果是毫无意义的,因为程序在执行之前和之后是相同的。 自我分配并不总是显而易见的。假设许多 STL 算法(分区、排序等)将对元素进行自分配是完全合理的。以上是关于api函数是啥意思,有啥分类?的主要内容,如果未能解决你的问题,请参考以下文章