mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8029 from ethereum/referenceTypes1
Update reference types (1).
This commit is contained in:
commit
cf6f6a51b0
@ -11,7 +11,8 @@ a variable of value type is used. Because of that, reference types have to be ha
|
|||||||
more carefully than value types. Currently, reference types comprise structs,
|
more carefully than value types. Currently, reference types comprise structs,
|
||||||
arrays and mappings. If you use a reference type, you always have to explicitly
|
arrays and mappings. If you use a reference type, you always have to explicitly
|
||||||
provide the data area where the type is stored: ``memory`` (whose lifetime is limited
|
provide the data area where the type is stored: ``memory`` (whose lifetime is limited
|
||||||
to a function call), ``storage`` (the location where the state variables are stored)
|
to an external function call), ``storage`` (the location where the state variables
|
||||||
|
are stored, where the lifetime is limited to the lifetime of a contract)
|
||||||
or ``calldata`` (special data location that contains the function arguments,
|
or ``calldata`` (special data location that contains the function arguments,
|
||||||
only available for external function call parameters).
|
only available for external function call parameters).
|
||||||
|
|
||||||
@ -23,7 +24,7 @@ while assignments inside the same data location only copy in some cases for stor
|
|||||||
Data location
|
Data location
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
Every reference type, i.e. *arrays* and *structs*, has an additional
|
Every reference type has an additional
|
||||||
annotation, the "data location", about where it is stored. There are three data locations:
|
annotation, the "data location", about where it is stored. There are three data locations:
|
||||||
``memory``, ``storage`` and ``calldata``. Calldata is only valid for parameters of external contract
|
``memory``, ``storage`` and ``calldata``. Calldata is only valid for parameters of external contract
|
||||||
functions and is required for this type of parameter. Calldata is a non-modifiable,
|
functions and is required for this type of parameter. Calldata is a non-modifiable,
|
||||||
@ -42,19 +43,29 @@ Data location and assignment behaviour
|
|||||||
|
|
||||||
Data locations are not only relevant for persistency of data, but also for the semantics of assignments:
|
Data locations are not only relevant for persistency of data, but also for the semantics of assignments:
|
||||||
|
|
||||||
* Assignments between ``storage`` and ``memory`` (or from ``calldata``) always create an independent copy.
|
* Assignments between ``storage`` and ``memory`` (or from ``calldata``)
|
||||||
* Assignments from ``memory`` to ``memory`` only create references. This means that changes to one memory variable are also visible in all other memory variables that refer to the same data.
|
always create an independent copy.
|
||||||
* Assignments from ``storage`` to a local storage variable also only assign a reference.
|
* Assignments from ``memory`` to ``memory`` only create references. This means
|
||||||
* All other assignments to ``storage`` always copy. Examples for this case are assignments to state variables or to members of local variables of storage struct type, even if the local variable itself is just a reference.
|
that changes to one memory variable are also visible in all other memory
|
||||||
|
variables that refer to the same data.
|
||||||
|
* Assignments from ``storage`` to a **local** storage variable also only
|
||||||
|
assign a reference.
|
||||||
|
* All other assignments to ``storage`` always copy. Examples for this
|
||||||
|
case are assignments to state variables or to members of local
|
||||||
|
variables of storage struct type, even if the local variable
|
||||||
|
itself is just a reference.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
pragma solidity >=0.4.0 <0.7.0;
|
pragma solidity >=0.4.0 <0.7.0;
|
||||||
|
|
||||||
contract C {
|
contract C {
|
||||||
uint[] x; // the data location of x is storage
|
// The data location of x is storage.
|
||||||
|
// This is the only place where the
|
||||||
|
// data location can be omitted.
|
||||||
|
uint[] x;
|
||||||
|
|
||||||
// the data location of memoryArray is memory
|
// The data location of memoryArray is memory.
|
||||||
function f(uint[] memory memoryArray) public {
|
function f(uint[] memory memoryArray) public {
|
||||||
x = memoryArray; // works, copies the whole array to storage
|
x = memoryArray; // works, copies the whole array to storage
|
||||||
uint[] storage y = x; // works, assigns a pointer, data location of y is storage
|
uint[] storage y = x; // works, assigns a pointer, data location of y is storage
|
||||||
@ -96,7 +107,7 @@ as C.
|
|||||||
Indices are zero-based, and access is in the opposite direction of the
|
Indices are zero-based, and access is in the opposite direction of the
|
||||||
declaration.
|
declaration.
|
||||||
|
|
||||||
For example, if you have a variable ``uint[][5] x memory``, you access the
|
For example, if you have a variable ``uint[][5] memory x``, you access the
|
||||||
second ``uint`` in the third dynamic array using ``x[2][1]``, and to access the
|
second ``uint`` in the third dynamic array using ``x[2][1]``, and to access the
|
||||||
third dynamic array, use ``x[2]``. Again,
|
third dynamic array, use ``x[2]``. Again,
|
||||||
if you have an array ``T[5] a`` for a type ``T`` that can also be an array,
|
if you have an array ``T[5] a`` for a type ``T`` that can also be an array,
|
||||||
@ -122,9 +133,11 @@ length or index access.
|
|||||||
|
|
||||||
Solidity does not have string manipulation functions, but there are
|
Solidity does not have string manipulation functions, but there are
|
||||||
third-party string libraries. You can also compare two strings by their keccak256-hash using
|
third-party string libraries. You can also compare two strings by their keccak256-hash using
|
||||||
``keccak256(abi.encodePacked(s1)) == keccak256(abi.encodePacked(s2))`` and concatenate two strings using ``abi.encodePacked(s1, s2)``.
|
``keccak256(abi.encodePacked(s1)) == keccak256(abi.encodePacked(s2))`` and
|
||||||
|
concatenate two strings using ``abi.encodePacked(s1, s2)``.
|
||||||
|
|
||||||
You should use ``bytes`` over ``byte[]`` because it is cheaper, since ``byte[]`` adds 31 padding bytes between the elements. As a general rule,
|
You should use ``bytes`` over ``byte[]`` because it is cheaper,
|
||||||
|
since ``byte[]`` adds 31 padding bytes between the elements. As a general rule,
|
||||||
use ``bytes`` for arbitrary-length raw byte data and ``string`` for arbitrary-length
|
use ``bytes`` for arbitrary-length raw byte data and ``string`` for arbitrary-length
|
||||||
string (UTF-8) data. If you can limit the length to a certain number of bytes,
|
string (UTF-8) data. If you can limit the length to a certain number of bytes,
|
||||||
always use one of the value types ``bytes1`` to ``bytes32`` because they are much cheaper.
|
always use one of the value types ``bytes1`` to ``bytes32`` because they are much cheaper.
|
||||||
@ -140,9 +153,10 @@ always use one of the value types ``bytes1`` to ``bytes32`` because they are muc
|
|||||||
Allocating Memory Arrays
|
Allocating Memory Arrays
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
You must use the ``new`` keyword to create arrays with a runtime-dependent length in memory.
|
Memory arrays with dynamic length can be created using the ``new`` operator.
|
||||||
As opposed to storage arrays, it is **not** possible to resize memory arrays (e.g. by assigning to
|
As opposed to storage arrays, it is **not** possible to resize memory arrays (e.g.
|
||||||
the ``.length`` member). You either have to calculate the required size in advance
|
the ``.push`` member functions are not available).
|
||||||
|
You either have to calculate the required size in advance
|
||||||
or create a new memory array and copy every element.
|
or create a new memory array and copy every element.
|
||||||
|
|
||||||
::
|
::
|
||||||
@ -172,7 +186,9 @@ type of the array.
|
|||||||
Array literals are always statically-sized memory arrays.
|
Array literals are always statically-sized memory arrays.
|
||||||
|
|
||||||
In the example below, the type of ``[1, 2, 3]`` is
|
In the example below, the type of ``[1, 2, 3]`` is
|
||||||
``uint8[3] memory``. Because the type of each of these constants is ``uint8``, if you want the result to be a ``uint[3] memory`` type, you need to convert the first element to ``uint``.
|
``uint8[3] memory``. Because the type of each of these constants is ``uint8``, if
|
||||||
|
you want the result to be a ``uint[3] memory`` type, you need to convert
|
||||||
|
the first element to ``uint``.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
@ -187,7 +203,8 @@ In the example below, the type of ``[1, 2, 3]`` is
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Fixed size memory arrays cannot be assigned to dynamically-sized memory arrays, i.e. the following is not possible:
|
Fixed size memory arrays cannot be assigned to dynamically-sized
|
||||||
|
memory arrays, i.e. the following is not possible:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user