define() vs const 该如何选择?

使用 define(),除非考虑到可读性、类常量、或关注微优化

1、在 PHP 中是使用 define() 函数来定义常量,PHP 5.3.0 以后,PHP 中也能够使用 const 关键字来声明常量了,一个常量一旦被定义,就不能再改变或者取消定义

2、常量只能包含标量数据(booleanintegerfloatstring)。可以定义 resource 常量,但应尽量避免,因为会造成不可预料的结果

3、可以简单的通过指定其名字来取得常量的值,与变量不同,不应该在常量前面加上 $ 符号。如果常量名是动态的,也可以用函数 constant() 来获取常量的值。用 get_defined_constants() 可以获得所有已定义的常量列表

Note: 常量和(全局)变量在不同的名字空间中。这意味着例如 TRUE$TRUE 是不同的

常量和变量有如下不同

常量前面没有美元符号($);
常量只能用 define() 函数定义,而不能通过赋值语句;
常量可以不用理会变量的作用域而在任何地方定义和访问;
常量一旦定义就不能被重新定义或者取消定义;
常量的值只能是标量。

define vs const

1、define() 在执行期定义常量,使用 const 关键字定义常量必须处于最顶端的作用区域,因为用此方法是在编译时定义的,这就意味着不能在函数内,循环内以及 if 语句之内用 const 来定义常量,这样 const 就有轻微的速度优势, 但不值得考虑这个问题

2、define() 将常量放入全局作用域,虽然你可以在常量名中包含命名空间, 这意味着你不能使用 define() 定义类常量

3、define() 允许你在常量名和常量值中使用表达式,而 const 则都不允许,这使得 define() 更加灵活

示例

1、const不能使用条件表达式定义常量. 如果要定义一个全局常量,只能在表达式外面

if (...) {
    const FOO = ‘BAR‘;    // invalid
}
// but
if (...) {
    define(‘FOO‘, ‘BAR‘); // valid
}

2、const 可以使用一个静态标量 (number, string or other constant like true, false, null, __FILE__), 反之define()没有限制.不过从 PHP 5.6 之后可以使用常量表达式

const BIT_5 = 1 << 5;    // valid since PHP 5.6, invalid previously
define(‘BIT_5‘, 1 << 5); // always valid

3、const 使用一个普通的常量名称 反之define() 可以使用任意的常量表达式

for ($i = 0; $i < 32; ++$i) {
    define(‘BIT_‘ . $i, 1 << $i);
}

4、const总是大小写敏感的, 反之define() 允许你定义一个大小写不敏感的常量通过第三个参数

define(‘FOO‘, ‘BAR‘, true);
echo FOO; // BAR
echo foo; // BAR

5、const simply reads nicer. It‘s a language construct instead of a function and also is consistent with how you define constants in classes,const defines a constant in the current namespace, while define() has to be passed the full namespace name:

namespace A\B\C;
// To define the constant A\B\C\FOO:
const FOO = ‘BAR‘;
define(‘A\B\C\FOO‘, ‘BAR‘);

6、Since PHP 5.6 const constants can also be arrays, while define() does not support arrays yet. However arrays will be supported for both cases in PHP 7.

const FOO = [1, 2, 3];    // valid in PHP 5.6
define(‘FOO‘, [1, 2, 3]); // invalid in PHP 5.6, valid in PHP 7.0

As consts are language constructs and defined at compile time they are a bit faster than define().

It is well known that PHP define() are slow when using a large number of constants. People have even invented things like apc_load_constants() and hidef to get around this.

consts make the definition of constants approximately twice as fast (on development machines with XDebug turned on even more). Lookup time on the other hand does not change (as both constant types share the same lookup table)

Finally, note that const can also be used within a class or interface to define a class constant or interface constant. define cannot be used for this purpose:

class Foo {
    const BAR = 2; // valid
}
// but
class Baz {
    define(‘QUX‘, 2); // invalid
}

Summary

Unless you need any type of conditional or expressional definition, use consts instead of define()s - simply for the sake of readability!

<?php
// 来看看这两种方法如何处理 namespaces
namespace MiddleEarth\Creatures\Dwarves;
const GIMLI_ID = 1;
define(‘MiddleEarth\Creatures\Elves\LEGOLAS_ID‘, 2);

echo(\MiddleEarth\Creatures\Dwarves\GIMLI_ID);  // 1
echo(\MiddleEarth\Creatures\Elves\LEGOLAS_ID);  // 2; 注意:我们使用了 define()

// Now let‘s declare some bit-shifted constants representing ways to enter Mordor.
define(‘TRANSPORT_METHOD_SNEAKING‘, 1 << 0); // OK!
const TRANSPORT_METHOD_WALKING = 1 << 1; //Compile error! const can‘t use expressions as values

// 接下来, 条件常量。
define(‘HOBBITS_FRODO_ID‘, 1);

if($isGoingToMordor){
    define(‘TRANSPORT_METHOD‘, TRANSPORT_METHOD_SNEAKING); // OK!
    const PARTY_LEADER_ID = HOBBITS_FRODO_ID // 编译错误: const 不能用于 if 块中
}

// 最后, 类常量
class OneRing{
    const MELTING_POINT_DEGREES = 1000000; // OK!
    define(‘SHOW_ELVISH_DEGREES‘, 200); // 编译错误: 在类内不能使用 define()
}
?>

无论你选择哪一种,请保持一致

看一下define在内核中如何实现的

/* {{{ proto bool define(string constant_name, mixed value, boolean case_insensitive=false)
   Define a new constant */
ZEND_FUNCTION(define)
{
	char *name;
	int name_len;
	zval *val;
	zval *val_free = NULL;
	zend_bool non_cs = 0;
	int case_sensitive = CONST_CS;
	zend_constant c;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|b", &name, &name_len, &val, &non_cs) == FAILURE) {
		return;
	}

	if(non_cs) {
		case_sensitive = 0;
	}

	/* class constant, check if there is name and make sure class is valid & exists */
	if (zend_memnstr(name, "::", sizeof("::") - 1, name + name_len)) {
		zend_error(E_WARNING, "Class constants cannot be defined or redefined");
		RETURN_FALSE;
	}

repeat:
	switch (Z_TYPE_P(val)) {
		case IS_LONG:
		case IS_DOUBLE:
		case IS_STRING:
		case IS_BOOL:
		case IS_RESOURCE:
		case IS_NULL:
			break;
		case IS_OBJECT:
			if (!val_free) {
				if (Z_OBJ_HT_P(val)->get) {
					val_free = val = Z_OBJ_HT_P(val)->get(val TSRMLS_CC);
					goto repeat;
				} else if (Z_OBJ_HT_P(val)->cast_object) {
					ALLOC_INIT_ZVAL(val_free);
					if (Z_OBJ_HT_P(val)->cast_object(val, val_free, IS_STRING TSRMLS_CC) == SUCCESS) {
						val = val_free;
						break;
					}
				}
			}
			/* no break */
		default:
			zend_error(E_WARNING,"Constants may only evaluate to scalar values");
			if (val_free) {
				zval_ptr_dtor(&val_free);
			}
			RETURN_FALSE;
	}

	c.value = *val;
	zval_copy_ctor(&c.value);
	if (val_free) {
		zval_ptr_dtor(&val_free);
	}
	c.flags = case_sensitive; /* non persistent */
	c.name = IS_INTERNED(name) ? name : zend_strndup(name, name_len);
	if(c.name == NULL) {
		RETURN_FALSE;
	}
	c.name_len = name_len+1;
	c.module_number = PHP_USER_CONSTANT;
	if (zend_register_constant(&c TSRMLS_CC) == SUCCESS) {
		RETURN_TRUE;
	} else {
		RETURN_FALSE;
	}
}
/* }}} */

/* {{{ proto bool defined(string constant_name)
   Check whether a constant exists */
ZEND_FUNCTION(defined)
{
	char *name;
	int name_len;
	zval c;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
		return;
	}

	if (zend_get_constant_ex(name, name_len, &c, NULL, ZEND_FETCH_CLASS_SILENT TSRMLS_CC)) {
		zval_dtor(&c);
		RETURN_TRUE;
	} else {
		RETURN_FALSE;
	}
}
/* }}} */

const

ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
{
	char *lowercase_name = NULL;
	char *name;
	int ret = SUCCESS;
	ulong chash = 0;

#if 0
	printf("Registering constant for module %d\n", c->module_number);
#endif

	if (!(c->flags & CONST_CS)) {
		/* keep in mind that c->name_len already contains the ‘\0‘ */
		lowercase_name = estrndup(c->name, c->name_len-1);
		zend_str_tolower(lowercase_name, c->name_len-1);
		lowercase_name = (char*)zend_new_interned_string(lowercase_name, c->name_len, 1 TSRMLS_CC);
		name = lowercase_name;
		chash = IS_INTERNED(lowercase_name) ? INTERNED_HASH(lowercase_name) : 0;
	} else {
		char *slash = strrchr(c->name, ‘\\‘);
		if(slash) {
			lowercase_name = estrndup(c->name, c->name_len-1);
			zend_str_tolower(lowercase_name, slash-c->name);
			lowercase_name = (char*)zend_new_interned_string(lowercase_name, c->name_len, 1 TSRMLS_CC);
			name = lowercase_name;

			chash = IS_INTERNED(lowercase_name) ? INTERNED_HASH(lowercase_name) : 0;
		} else {
			name = c->name;
		}
	}
	if (chash == 0) {
		chash = zend_hash_func(name, c->name_len);
	}

	/* Check if the user is trying to define the internal pseudo constant name __COMPILER_HALT_OFFSET__ */
	if ((c->name_len == sizeof("__COMPILER_HALT_OFFSET__")
		&& !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1))
		|| zend_hash_quick_add(EG(zend_constants), name, c->name_len, chash, (void *) c, sizeof(zend_constant), NULL)==FAILURE) {

		/* The internal __COMPILER_HALT_OFFSET__ is prefixed by NULL byte */
		if (c->name[0] == ‘\0‘ && c->name_len > sizeof("\0__COMPILER_HALT_OFFSET__")
			&& memcmp(name, "\0__COMPILER_HALT_OFFSET__", sizeof("\0__COMPILER_HALT_OFFSET__")) == 0) {
			name++;
		}
		zend_error(E_NOTICE,"Constant %s already defined", name);
		str_free(c->name);
		if (!(c->flags & CONST_PERSISTENT)) {
			zval_dtor(&c->value);
		}
		ret = FAILURE;
	}
	if (lowercase_name && !IS_INTERNED(lowercase_name)) {
		efree(lowercase_name);
	}
	return ret;
}

参考

时间: 2024-10-11 23:24:09

define() vs const 该如何选择?的相关文章

define vs const vs enum

以前用C,习惯了define:const,enum 什么的基本不太会用,现在有时间整理一下. /***********************************************************************************************************/ define:宏定义,在预编译阶段,编译器将宏作简单替换.比如: #define SUNDAY 7 在预编译阶段,凡是文本中出现SUNDAY的地方,编译器就会将其用7来代替.这样的好处显

PHP中定义常量define与const

我们通常把不经常变的值定义成常量,常量一般用全部大写来表示,前面不加美元符号,也可减少团队开发的出错.那么define和const有什么区别呢? 1.const是一个语言结构:而define是一个函数,可以通过第三个参数来指定是否区分大小写.true表示大小写不敏感,默认为false define('PI', 3.14, true); 2.const简单易读,编译时要比define快很多. 3.const可在类中使用,用于类成员常量定义,定义后不可修改:define不能在类中使用,可用于全局变量

c++中 #define和const的区别

来源参考:https://blog.csdn.net/yi_ming_he/article/details/70405364 这个区别用从几个角度来说: 角度1: 就定义常量说的话:  const 定义的常数是变量 也带类型, #define 定义的只是个常数 不带类型. 角度2: 就起作用的阶段而言: define是在编译的预处理阶段起作用,而const是在 编译.运行的时候起作用. 角度3: 就起作用的方式而言: define只是简单的字符串替换,没有类型检查.而const有对应的数据类型,

PHP常量定义define与const

一.const PHP5.3以前,const只能在类内部声明变量,5.3+允许在外部声明变量,但还不能使用常量计算! const ONE = 1; const WORD = 'hello world'; PHP5.6开始,const支持包括数值.字符串字面量以及其他常量在内的数值表达式,进行常量定义.并且更重要的是const开始支持定义常量数组! const ONE = 1; const TWO = ONE * 2; const ARR = ['a', 'b']; 需要注意的是const并不支持

#define、const、typedef的区别

#define 并不是定义变量, 只是用来做文本替换 例如: #define PI 3.1415926 float angel; angel=30*PI/180; 那么,当程序进行编译的时候,编译器会首先将 “#define PI 3.1415926”以后的,所有代码中的“Pi”全部换成 “3.1415926” 然后再进行编译. 我查到一个讲const与#define的差别的帖子,里面谈到const与#define最大的差别在于:前者在堆栈分配了空间,而后者只是把具体数值直接传递到目标变量罢了.

typedef和define,const,struct和typedef struct

先看几个例子 (1) struct{ int x; int y; }test1; 好,定义了 结构 test1, test1.x 和 test1.y 可以在语句里用了. (2) struct test {int x; int y; }test1; 好,定义了 结构 test1, test1.x 和 test1.y 可以在语句里用了. 与 1 比,省写 了 test (3) typedef struct test {int x; int y; }text1,text2; 只说了 这种结构 的(类型

iOS开发总结(A0)- #define 与 const

什么时候用#define ,什么时候用const ? effective objective c item4 中这样说: Prefer Typed Constants to Preprocessor #define 1. 避免 #define. 因为无类型信息,且可能会redefined 2. 在m文件中定义为 static const(实际上这种处理和#define一样) 3. 对于global constants,应在头文件中申明,在相关的m文件中定义,前缀为响应的类名称 如在.h 中, e

#define static const 用法 (转)

1.Define用法: define主要是用于宏常量定义的,使程序看起来更简洁明了,方便代码维护,#define定义的实质只是一个常数的名字,没有具体数据类型的,没有分配内存空间.在编译是会被编译器替换为该常数.每次使用该宏定义,就要进行编译并分配空间,若一个程序中多次使用define定义的数据,则就会有多份拷贝.这么做是为了提高程序的可读性,但安全性相对差点. 2.const用法: const定义的全局数据变量,其基本作用和define相同,但又在define的基础上增加了好多功能.const

define和const的区别

常量是一个简单值的标识符(名字).如同其名称所暗示的,在脚本执行期间该值不能改变(除了所谓的魔术常量,它们其实不是常量).常量默认为大小写敏感.通常常量标识符总是大写的. 可以用 define() 函数来定义常量.在 PHP 5.3.0 以后,可以使用 const 关键字在类定义的外部定义常量,先前版本const 关键字只能在类(class)中使用.一个常量一旦被定义,就不能再改变或者取消定义. 常量只能包含标量数据(boolean,integer,float 和 string). 可以定义 r