我应该避免在C ++中使用#define吗?为什么,我可以使用哪些替代品?

时间:2013-03-05 08:12:00

标签: c++ c-preprocessor preprocessor-directive

对于某些类型的程序,我需要使用常量高值来指示某些变量的某些属性。我的意思是,如果树中的color[i] = 1000000;节点未被探测,则允许i。但是我经常在最后错误地写出0的数量,所以我只是想知道这样做是否更好:

#define UNEXPLORED 1000000;
color[i] = UNEXPLORED;

我记得在某些地方我已经读到,避免使用#define要好得多。这样对吗?你会如何解决这个问题?

3 个答案:

答案 0 :(得分:4)

对于简单常量,您可以使用const或新constexpr

constexpr unsigned int UNEXPLORED = 1000000;

在这种情况下,使用constconstexpr之间没有区别。但是,标记为constexpr的“变量”在编译时进行评估,而不是在运行时进行评估,并且可以在只接受文字的地方使用。

答案 1 :(得分:3)

例如使用常量。

const unsigned int UNEXPLORED = 1000000;

或枚举

enum { UNEXPLORED = 1000000 };

答案 2 :(得分:0)

在常量的使用中,上面的两个答案是正确的,但#define并不仅限于使用。{1}}。另一个使用#define的例子是宏。

<强>宏

宏是预处理器使用的代码片段,它们的工作方式与其他#define声明完全相同。预处理器将使用宏的代码逐字地替换您定义的符号的出现。一个例子:

#define HELLO_MAC do{ std::cout << "Hello World" << std::endl; }while(false)

int main(int argc, char** argv)
{
     HELLO_MAC;
}

这将使用我声明的代码逐字地替换HELLO_MAC符号。如果它是一个常数,它会做同样的事情。因此,您可以将常量#define视为一种特殊的宏。

使用宏,您还可以传递参数,这对于通过代码强制执行日志记录/异常策略特别有用。 例如

#define THROW_EXCEPT( ex_type, ex_msg ) /
    do{ throw ex_type( buildExString( (ex_msg), __LINE__, __FILE__ ) ); }while(false)

... 
// somewhere else
THROW_EXCEPT( std::runtime_error, "Unsupported operation in current state" );

该代码允许我确保每个人都记录引发异常的文件行。

模板通常是一个更好的选择而不是宏,但是我不能在这个例子中使用模板函数,因为我需要在throw的位置使用__LINE____FILE__函数,而不是模板功能的位置。

你应该在哪里使用宏?你可以在任何地方使用其他东西与任何#define一样,宏都经过预处理,因此编译器根本看不到它们。这意味着永远不会为HELLO_MACTHROW_EXCEPT创建任何符号,因此无法在调试器中看到它们。如果遇到编译错误,它们也会令人困惑,特别是如果它们是长宏。