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", ¶meter) == 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_