C ++中的宏和const之间的区别是什么? [英] What is the difference between a macro and a const in C++?

查看:252
本文介绍了C ++中的宏和const之间的区别是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在技术面试中被问过这个问题:


const 和C ++中的宏?


我的答案是宏是一个预处理器指令,如果使用宏,则调试应用程序,因为它在编译之前被替换为常量表达式,而 const 可以具有类型标识符并且易于调试。



编辑:

p>

从C ++的IBM文档:


c $ c> #define const 类型限定符:


  1. #define 指令可用于为数字,字符或字符串常量创建名称,而任何类型的const对象都可以


  2. 一个const对象受变量的作用域规则约束,而使用 #define 不是。与 const 对象不同,宏的值不会显示在编译器使用的中间源代码中,因为它们是内联扩展的。


  3. 宏可以用于常量表达式,例如数组边界,而 const 对象不能。 (我认为我们肯定需要使用宏来定义 array_size


  4. <检查宏,包括宏参数。




解决方案

宏和常量不是远程的相同的东西,每个有时是适合的情况,你的答案只是划伤表面的差异。而且,C + +有两种不同的常数。



const 限定符定义的常数最好被认为是不可修改的变量 。它有一个变量的所有属性:它有一个类型,它有一个大小,它有连接,你可以取它的地址(编译器可能会优化掉一些这些属性,如果它可以摆脱它: ,其地址从不使用的常量可能不会被发射到可执行映像中,但是这只是通过as-if规则的优雅)。你不能对 const code> datum将更改其值。用枚举定义的常量有点不同。它有一个类型和一个大小,但它没有链接,你不能取它的地址,它的类型是唯一的。这两个都在翻译阶段7期间处理,因此它们不能是除了左值或右值之外的任何东西。 (我对前面句子中的术语很抱歉,但是我将不得不写几个段落。)



宏有更少的约束:它可以扩展任何序列的标记,只要整个程序仍然是一个良好的程序。它没有变量的任何属性。将 sizeof & 应用于宏可能会或可能不会做一些有用的事情,这取决于宏展开的内容。宏有时被定义为扩展为数字文字,这样的宏有时被视为常量,但它们不是:编译器正确(即,翻译阶段7)将它们视为<

通常认为这是一个好的做法,现在,当一个常数会做时,不要使用宏。宏不遵守与所有其他标识符相同的作用域规则,这可能令人困惑,如果使用常量,您可以向翻译阶段7提供更多信息,因此也可以向调试器提供更多信息。但是,宏允许你做任何其他方式不能做的事情,如果你需要做一个这样的事情,你应该毫不犹豫地使用它们。 (宏在拉他们的体重,在这个意义上,通常不会只是展开到数字文字,虽然我不会说永远不会。)



编辑:下面是一个宏观做一些有趣事情的例子。它绝不是形状或形式的恒定。可能有一种方法可以获得相同的效果,而没有宏(如果你知道一个不涉及stringstreams,我会很好奇地听到它!)但我认为它使一个很好的插图的权力和宏的危险(对于后者,考虑如果在一个非常具体的上下文之外使用它会做什么...)

  static double elapsed()
{...}
#define ELAPSED'['< std :: fixed<< std :: setprecision(2)<< elapsed()<< ]

//用法:
for(vector< string> :: iterator f = files.begin(); f!= files.end(); f ++){
cout<< ELAPSED<< reading file:< * f < '\\\
';
process_file(* f);
}


I was asked this question in a technical interview:

What is the difference between a const and a macro in C++?

My answer was that a macro is a preprocessor directive and it could be difficult to debug the application if you use a macro since it is replaced with the constant expression before compilation, whereas a const can have a type identifier and is easy to debug.

Could anyone point out any other difference and which should be preferred?

EDIT:

From the IBM documentation for C++:

The following are some differences between #define and the const type qualifier:

  1. The #define directive can be used to create a name for a numerical, character, or string constant, whereas a const object of any type can be declared.

  2. A const object is subject to the scoping rules for variables, whereas a constant created using #define is not. Unlike a const object, the value of a macro does not appear in the intermediate source code used by the compiler because they are expanded inline. The inline expansion makes the macro value unavailable to the debugger.

  3. A macro can be used in a constant expression, such as an array bound, whereas a const object cannot. (I think we surely need to use macro to define array_size.

  4. The compiler does not type-check a macro, including macro arguments.

解决方案

Macros and constants are not remotely the same thing, each is sometimes appropriate for the circumstances, and your answer only scratches at the surface of the difference. Also, C++ has two different kinds of constants.

A constant defined with the const qualifier is best thought of as an unmodifiable variable. It has all the properties of a variable: it has a type, it has a size, it has linkage, you can take its address. (The compiler might optimize away some of these properties if it can get away with it: for instance, constants whose address is never used may not get emitted into the executable image. But this is only by the grace of the as-if rule.) The only thing you can't do to a const datum is change its value. A constant defined with enum is a little different. It has a type and a size, but it doesn't have linkage, you can't take its address, and its type is unique. Both of these are processed during translation phase 7, so they can't be anything but an lvalue or rvalue. (I'm sorry about the jargon in the preceding sentence, but I would have to write several paragraphs otherwise.)

A macro has far fewer constraints: it can expand to any sequence of tokens, as long as the overall program remains a well-formed program. It doesn't have any of the properties of a variable. Applying sizeof or & to a macro may or may not do something useful, depending on what the macro expands to. Macros are sometimes defined to expand to numeric literals, and such macros are sometimes thought of as constants, but they're not: "the compiler proper" (that is, translation phase 7) sees them as numeric literals.

It is generally considered good practice, nowadays, not to use a macro when a constant will do. Macros don't obey the same scoping rules as all other identifiers, which can be confusing, and if you use a constant you give more information to translation phase 7 and thus also to the debugger. However, macros permit you to do things that cannot be done any other way, and if you need to do one of those things, you should not hesitate to use them. (Macros that are pulling their weight, in this sense, generally do not just expand to numeric literals, though I am not going to say never.)

EDIT: Here's an example of a macro doing something interesting. It is in no way, shape or form a constant. There may well be a way to get the same effect without a macro (if you know one that doesn't involve stringstreams, I'd be curious to hear about it!) but I think it makes a good illustration of both the power and the danger of macros (for the latter, consider what it would do if it was used outside of one very specific context...)

static double elapsed()
{ ... }
#define ELAPSED '[' << std::fixed << std::setprecision(2) << elapsed() << "] "

// usage:
for (vector<string>::iterator f = files.begin(); f != files.end(); f++) {
    cout << ELAPSED << "reading file: " << *f << '\n';
    process_file(*f);
}

这篇关于C ++中的宏和const之间的区别是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆