对于某些类型的程序,我需要使用恒定的高值来指示某些变量的某些属性。我的意思是color[i] = 1000000;
如果i
树中的节点未被探索,则让。但是我经常在最后写错 0 的数量,所以我只是想知道这样做是否更好:
#define UNEXPLORED 1000000;
color[i] = UNEXPLORED;
我记得在某处我读到过,最好避免使用#define。这样对吗?你将如何解决这个问题?
对于某些类型的程序,我需要使用恒定的高值来指示某些变量的某些属性。我的意思是color[i] = 1000000;
如果i
树中的节点未被探索,则让。但是我经常在最后写错 0 的数量,所以我只是想知道这样做是否更好:
#define UNEXPLORED 1000000;
color[i] = UNEXPLORED;
我记得在某处我读到过,最好避免使用#define。这样对吗?你将如何解决这个问题?
对于简单的常量,您可以使用或者使用const
new constexpr
:
constexpr unsigned int UNEXPLORED = 1000000;
const
在这种情况下,使用和没有区别constexpr
。但是,标记的“变量”constexpr
在编译时而不是在运行时进行评估,并且可以在仅接受文字的地方使用。
例如使用常量。
const unsigned int UNEXPLORED = 1000000;
或枚举
enum { UNEXPLORED = 1000000 };
在使用常量时,上面的两个答案是正确的,但#define
不限于单独使用。另一个使用的例子#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
用于常量的 s 视为一种特殊的宏。
使用宏您还可以传递参数,我发现它对于在代码上执行日志记录/异常策略特别有用。例如
#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__
and__FILE__
函数,而不是从模板函数的位置。
哪里不应该使用宏?你可以在任何地方使用其他东西。像任何宏一样,宏#define
是经过预处理的,因此编译器根本看不到它们。这意味着永远不会为HELLO_MAC
or创建任何符号THROW_EXCEPT
,因此在调试器中看不到它们。如果您遇到编译错误,它们也可能会令人困惑,尤其是当它们是长宏时。