1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
|
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision: 297078 $ -->
<sect2 xml:id="internals2.ze1.zendapi.copy-constructor" xmlns="http://docbook.org/ns/docbook">
<title>Duplicating Variable Contents: The Copy Constructor</title>
<para>
Sooner or later, you may need to assign the contents of one
<envar>zval</envar> container to another. This is easier said than
done, since the <envar>zval</envar> 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
<envar>zval</envar> to another, you avoid duplicating the hash
table entries, using only a reference to them (at most).
</para>
<para>
To copy this complex kind of data, use the <emphasis>copy
constructor</emphasis>. 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
rvalue (result of the evaluation of the right side of the operator)
to the lvalue (same for the left side).
</para>
<para>
<emphasis>Overloading</emphasis> 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).
</para>
<para>
This same form of "extended copying" is also necessary for PHP's
<envar>zval</envar> 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.
</para>
<para>
Zend ships with such a function,
called <function>zend_copy_ctor</function> (the previous PHP equivalent
was <function>pval_copy_constructor</function>).
</para>
<para>
A most useful demonstration is a function that accepts a complex type as
argument, modifies it, and then returns the argument:
</para>
<programlisting role="c">
<![CDATA[
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);
]]>
</programlisting>
<para>
The first part of the function is plain-vanilla argument retrieval.
After the (left out) modifications, however, it gets interesting:
The container of <envar>parameter</envar> is assigned to the
(predefined) <envar>return_value</envar> 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
<literal>FAILURE</literal> on failure and
<literal>SUCCESS</literal> on success.
</para>
<para>
If you omit the call to the copy constructor in this example, both
<envar>parameter</envar> and <envar>return_value</envar> would
point to the same internal data, meaning that
<envar>return_value</envar> would be an illegal additional
reference to the same data structures. Whenever changes occurred in
the data that <envar>parameter</envar> points to,
<envar>return_value</envar> might be affected. Thus, in order to
create separate copies, the copy constructor must be used.
</para>
<para>
The copy constructor's counterpart in the Zend API, the destructor
<function>zval_dtor</function>, does the opposite of the
constructor.
</para>
</sect2>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->
|