c++ 中__declspec 的用法详解

2020-01-06 15:59:00于丽

8. noinline__declspec(noinline)

告诉编译器不去内联一个具体函数。

9. noreturn__declspec(noreturn)

告诉编译器没有返回值.注意添加__declspec(noreturn)到一个不希望返回的函数会导致已没有定义错误.

10.nothrow__declspec(nothrow)

用于函数声明,它告诉编译器函数不会抛出异常。

e.g


#define WINAPI __declspec(nothrow) __stdcall
void WINAPI f1();
void __declspec(nothrow) __stdcall f2();
void __stdcall f3() throw();

11.novtable __declspec(novtable)

用在任意类的声明,但是只用在纯虚接口类,因此这样的不能够被自己实例话.它阻止编译器初始化虚表指针在构造和析构类的时候,这将移除对关联到类的虚表的 引用.如果你尝试这实例化一个有novtable关键字的类,它将发生AV(access violation)错误.C++里virtual的缺陷就是vtable会增大代码的尺寸,在不需要实例化的类或者纯虚接口的时候,用这个关键字可以减 小代码的大小.

e.g


#if _MSC_VER >= 1100 && !defined(_DEBUG)
#define AFX_NOVTABLE __declspec(novtable)
#else
#define AFX_NOVTABLE
#endif
....
class AFX_NOVTABLE CObject
{
...
};

这是vc里面的一段代码,我们可以看出编译Release版本时,在CObject前是__declspec(novtable),在debug版本没有这个限制。

e.g


#include <stdio.h>
struct __declspec(novtable) X
{ 
virtual void mf();
};
struct Y : public X 
{ 
void mf() 
{ 
printf_s("In Yn"); 
}
};

12.selectany的作用

__declspec(selectany)可以让我们在.h文件中初始化一个全局变量而不是只能放在.cpp中。比如有一个类,其中有一个静态变量,那 么我们可以在.h中通过类似" __declspec(selectany) type class::variable = value; "这样的代码来初始化这个全局变量。既是该.h被多次include,链接器也会为我们剔除多重定义的错误。这个有什么好处呢,我觉得对于 teamplate的编程会有很多便利。

e.g


class test
{
public: 
static int t;
};
__declspec(selectany) int test::t = 0; 

13.thread 

thread 用于声明一个线程本地变量. __declspec(thread)的前缀是Microsoft添加给Visual C++编译器的一个修改符。它告诉编译器,对应的变量应该放入可执行文件或DLL文件中它的自己的节中。__declspec(thread)后面的变量 必须声明为函数中(或函数外)的一个全局变量或静态变量。不能声明一个类型为__declspec(thread)的局部变量。

e.g


__declspec(thread) 
class X{
public: 
int I; 
} x; // x is a thread objectX y; // y is not a thread object 

14.uuid__declspec(uuid)

用于编译器关联一个GUID到一个有uuid属性的类或结构的声明或者定义.