Sooner or later, you may need to assign the
contents of one
zval
container to another. This is easier said than done, since
the
zval
container doesn't contain only type information, but also
references to places in Zend's internal data. For example,
depending on their size, arrays and objects may be nested
with lots of hash table entries. By assigning one
zval
to another, you avoid duplicating the hash table entries,
using only a reference to them (at most).
To copy this complex kind of data, use the
copy constructor
. Copy constructors are typically defined in languages that
support operator overloading, with the express purpose of
copying complex types. If you define an object in such a
language, you have the possibility of overloading the "="
operator, which is usually responsible for assigning the
contents of the lvalue (result of the evaluation of the left
side of the operator) to the rvalue (same for the right
side).
Overloading
means assigning a different meaning to this operator, and is
usually used to assign a function call to an operator.
Whenever this operator would be used on such an object in a
program, this function would be called with the lvalue and
rvalue as parameters. Equipped with that information, it can
perform the operation it intends the "=" operator to have
(usually an extended form of copying).
This same form of "extended copying" is also
necessary for PHP's
zval
containers. Again, in the case of an array, this extended
copying would imply re-creation of all hash table entries
relating to this array. For strings, proper memory allocation
would have to be assured, and so on.
Zend ships with such a function, called
zend_copy_ctor()
(the previous PHP equivalent was
pval_copy_constructor()
).
A most useful demonstration is a function that
accepts a complex type as argument, modifies it, and then
returns the argument:
zval *parameter; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", parameter) == FAILURE) return; } // do modifications to the parameter here // now we want to return the modified container: *return_value == *parameter; zval_copy_ctor(return_value); |
The first part of the function is plain-vanilla
argument retrieval. After the (left out) modifications,
however, it gets interesting: The container of
parameter
is assigned to the (predefined)
return_value
container. Now, in order to effectively duplicate its
contents, the copy constructor is called. The copy
constructor works directly with the supplied argument, and
the standard return values are
FAILURE
on failure and
SUCCESS
on success.
If you omit the call to the copy constructor in
this example, both
parameter
and
return_value
would point to the same internal data, meaning that
return_value
would be an illegal additional reference to the same data
structures. Whenever changes occurred in the data that
parameter
points to,
return_value
might be affected. Thus, in order to create separate copies,
the copy constructor must be used.
The copy constructor's counterpart in the Zend
API, the destructor
zval_dtor()
, does the opposite of the constructor.