User-defined conversion function and casting to reference. Allowing both rvalues and lvalues to be bound to an lvalue reference makes that impossible. foo now is null. (This is a more basic question that arose while I was thinking about this other recent. Naming expressions are always lvlaues. Either have a single function taking by value and moving from it, or have two functions, one taking lvalue ref and copying and one taking rvalue ref and moving. G. has an address). But in the circumstances of the linked question, the template instantiation of std::function cannot be inferred from the lambda type. It can convert lvalues to lvalue references and rvalues to rvalue references. If an l-value could bind to an r-value reference, that would mean the detection I was talking about. 1 Answer. Improve this answer. The array to pointer conversion occurs in most uses of an array in an expression, however, and so might surprise some people. Without this, the compiler will complain that you "cannot bind non-const lvalue reference of type 'std::string&' to an rvalue. . Sorted by: 7. It can convert between pointers. 区分左值和右值是很重要的,这是使用C++11 move语义的基础。. The difference between lvalues and rvalues plays a role in the writing and understanding of expressions. Assuming that “reference to cv1 T” is the type of the reference being initialized, and “cv S” is. 5. You can use the function template is_lvalue (below) to find out if an operand is an lvalue and use it in the function template isTernaryAssignable to find out if it can be assigned to. template <typename element, unsigned int size> class array { private. h, the output is same as Clang output it's reasonable. Similarly, rhs in Gadget. - tl:dr: Binding lvalues to rvalue-parameters is not allowed (except if the lvalue is a function), and binding rvalues to non-const lvalue-parameters is also not allowed (but const lvalue-parameters would be ok). universal reference. That is any named parameter of a function cannot be implicitly casted or used to initialize another rvalue reference; it only copies to lvalue references; but static_cast can explicitly cast the valueness of the reference. e. So in terms of the type analogy this means that cv T& and cv T&& are transformed to cv T if T is a class type and to T if T is a non-function non-array. In C++, non-const references can bind to lvalues and const references can bind to lvalues or rvalues, but there is nothing that can bind to a non-const rvalue. xvalue always refers to an expression. The type after conversion is not qualified by either const or volatile. const A& x = 1; //compile x = 2; //error! A&& xxx = 1; //compile A& xx = 1; //does not compile. Now an lvalue reference is a reference that binds to an lvalue. Note that this must wait until construction is complete for two reasons. The expression *this is an lvalue; A {} is an rvalue (prvalue) even though they designate the same temporary object. It shouldn't. c++ template type matching with references [duplicate] Ask Question Asked 5 days ago. lvalue references are marked with one ampersand (&). 1. In C++, an rvalue is a temporary object that does not have a stable location in memory. In the function, the argument has a name and thus is an lvalue. The object identified by an xvalue expression may be a nameless temporary, it may be a named object in scope, or any other kind of object, but if used as a function argument, xvalue will always bind to the rvalue reference overload if available. Informally, "lvalue-to-rvalue conversion" means "reading the value". I have tried to simulate the assignment of the object (pair. The only thing that can be an rvalue or an lvalue is an expression. cv]/4. However, it's type will be const std::string or std::string depending on the choice of const in the MyPair type. (This is somewhat of a simplification, in C++11 we have lvalues, xvalues and prvalues. std::forward<> will make sure to convert the "value category" x to match its type. (If you insist to know, the result of subscripting into an rvalue array used to be an lvalue in C++11, but is an xvalue in C++14 - issue 1213 . A minimal example:This is because of copy elision in C++. Here's what happens when we call move with lvalue: Object a; // a is lvalue Object b = std::move (a); and corresponding move instantiation:3. why std::forward converts both as rvalue reference. An rvalue (so-called, historically, because rvalues could appear on the right-hand side of an assignment expression) is an xvalue, a temporary object or subobject thereof, or a value that is not associated with an object. Template argument deduction deduces T to be X, so the parameter has type X&&. 1 Answer. That means std::move could take both lvalue and rvalue, and convert them to rvalue unconditionally. When you typecast an expression, the result of that expression is an rvalue rather than an lvalue. 2. Lvalue to rvalue conversion. If t returns by rvalue reference, you obtain a reference to whatever was returned. specifically, the argument expression is an rvalue that is bound to the rvalue reference parameter. It matches arguments of any value category, making t an lvalue reference if the supplied argument was an lvalue or an rvalue reference if the supplied argument was an rvalue. Every expression belongs to one of three value categories: lvalue, non-lvalue object (rvalue), and function designator. Therefore the usage of const rvalue references communicates thatAn lvalue is an expression representing an object that can have its address taken. In short: every named object is Lvalue, and even if v is reference to Rvalue you need to use move to force move ctor to be called. You would then need to add a destructor to AttrDec and delete the pointer in it and add a copy constructor. 0. If you pass an argument to a reference type parameter (whether lvalue or rvalue reference), the object will not be copied. The locator value is called lvalue, while the value resulting from evaluating that location is called rvalue. That is the historical origin of the letters l. You could disallow rvalues, but not sure if that would be acceptable. C. Move semantics relies on a new feature of C++11, called rvalue references, which you'll want to understand to really appreciate what's going on. 2. An obvious example of an lvalue expression is an identifier with suitable type and storage class. Cast to reference type. 106) This requires a conversion function (12. To set this compiler option in the Visual Studio development environment. The reference could be bound to the result of the implicit conversion if it wasn't non-const because the result of that implicit conversion is an rvalue i. Without lvalue-to-rvalue conversion, it cannot read it's value. The new version creates a temporary of type double for the conversion int -> double and binds. If element on this position doesn't exist, it should throw exception. goo<int> is an lvalue of function type, but expressions of function type are. To get a lvalue expression to the value pointed to by a pointer, just use the unary * operator. X& r = X(99); // ERRORI use forward declaration here to pass object of class B as parameter in class A. It's actually a cast. 3. You. 97 * @brief Convert a value to an rvalue. An lvalue or xvalue is an expression that refers to such an object. The output is: Copy constructor with lvalue reference. Rvalue references are a feature of C++ that was added with the C++11 standard. Correct, the epxression T() is always an rvalue for scalar and user-defined types T. [2] Then, the resulting value is placed in a temporary variable of type T. So MSVC++ is giving incorrect result (in case of C++ code). But in this particular case, the rules. For example in an expression. In this case 2*b is an rvalue since it does not persist beyond the expression. 1 is rvalue, it doesn't point anywhere, and it's contained within lvalue x. thus, this is legal: string&& s = foo (); // extends lifetime as before s += "bar"; baz (std::move (s)); // move the temporary into the baz function. lvalue. So when you bind the references the lvalue will have to be const. However, a (prvalue). If the target type is an inaccessible or ambiguous base of the. Abbreviations in this article. Expressions don't have return types, they have a type and - as it's known in the latest C++ standard - a value category. uint8Vect_t encodeData(uint8Vect_t &dataBuff); Here you are taking a reference to a uint8Vect_t. 5. We could categorize each expression by type or value. At the same time, we cannot move away from const values. For example, the left-hand side of an assignment expression to a primitive type must be an lvalue: int i; i = 3; is OK whereas 5 = 3 is not. Indeed it does. Visual Studio warning disappears if one removes std::move. 1: A glvalue of a non-function, non-array type T can be converted to a prvalue. For example in the following instructions. Read it along with, §4. 23. Except for an implicit object parameter, for which see 13. It shouldn't be something special so i coded that a component has a parent as composite, the composite should derrived from component and use the constructor from it's base class (Component). When you look at a parameter thing&& x its type is an rvalue reference, however, the variable named x also has a value category: it's an lvalue. Convert to rvalue references. It can convert lvalues to lvalue references and rvalues to rvalue references. C++0x rvalue reference template argument deduction. It's just that type of that lvalue is "rvalue reference to Key ". For the second overload, it would call operator const P&() const&. That is because arr is indeed an lvalue, as it is not a function designator, the result of [], or the. arg the variable has type int&& and no value category. 9. The lvalue to rvalue conversion isn't being done either, of course, but that's rather intuitive and normal. Note that there is one exception: there can be lvalue const reference binding to an rvalue. The rvalue-reference version can't be called with an lvalue argument. An lvalue is a value bound to a definitive region of memory whereas an rvalue is an expression value whose existence is temporary and who does not necessarily refer to a definitive region of memory. If type is an lvalue reference type or an rvalue reference to a function type, the cast result is an lvalue. Their very nature implies that the object is transient. Consequently, it's not legal to apply the ++ operator to the. That means std::move could take both lvalue and rvalue, and convert them to rvalue unconditionally. C++20 the conversion restriction regarding designated initializer lists was applied even if the parameter is a reference not restricted in this case P2468R2:Postfix operator++ requires the value-category of the operand to be an l-value, regardless of the type of the operand. It would capitalize std::strings, and display each parameter after they are capitalized. It's not an rvalue reference, but a forwarding reference; which could preserve the value category of the argument. e. It doesn't need to get the value of. Say we want to steal from an lvalue: int main() { Holder h1(1000); // h1 is an lvalue Holder h2(h1); // copy-constructor invoked (because of lvalue in input) } This will not work: since h2 receives an lvalue in input, the copy constructor is being triggered. 0) is not permitted in a core constant expression unless it meets one of three listed criteria (see C11 5. Write a function template to convert rvalues to lvalues: template<typename T> T &as_lvalue (T &&val) { return val; } Now, use it: deref (&as_lvalue (42)); Warning: this doesn't extend the lifetime of the temporary, so you mustn't use the returned reference after the end of the full-expression in which the temporary was. C++ 中有两种类型的表达式:. Informally this conversion is "evaluating" or "taking the value of" the object that the lvalue refers to. lvalue cannot be a function, expression (like a+b) or a constant (like 3 , 4 , etc. Assume a variable name as a label attached to its location in memory. The Lvalue refers to a modifiable object in c++ that can be either left or right side of the assignment operator. 1, a standard conversion sequence cannot be formed if it requires binding an lvalue reference to non-const to an rvalue or binding an rvalue reference. c++ base constructor lvalue to parameter. It is illegal in C++ to attach non-const references to rvalues. An lvalue-to-rvalue conversion is a conversion from a non-function, non-array lvalue or xvalue of type cv T to a prvalue of either type cv T if T is a class type or T if T is not a class type. — Otherwise, the reference shall be an lvalue reference to a non-volatile const type (i. A nice feature of this heuristic is that it helps you remember that the type of an expression is independent of. by unconditionally casting its argument—which might be an lvalue—to an rvalue reference, it enables the compiler to subsequently move, rather than copy, the value passed in Arg if its type is. Since int() isn't an lvalue, you can't assign to int(). 197. Because a non-const reference is always a lvalue, so the code works and result in a lvalue (i. For non-class types you cannot assign to rvalues. An lvalue-to-rvalue conversion (converting the name of the object x to its value 2. an rvalue reference). When I discovered this, it seemed odd to me, so I tried. lvalues. The r-value reference is a reference to the original object, so converting it to a l-value reference will just make a reference to the original object. The C++11 standard for lvalue and rvalue conversion can be found at chapter 4. C++11 also invented the forwarding reference: that when there’s a deduced type T directly modified by &&, T can sometimes be deduced as an lvalue reference type. However, Microsoft compiler does accept it meaning that. The purpose of r-value reference parameters is to detect specifically when an object is an r-value. From C++11 4. why std::forward converts both as rvalue reference. The confusion you're having is pretty common. Using rvalue references (C++11) Note: C++11 is a new version of the C++ programming language standard. The problem is that your method of differentiating lvalues from rvalues with func is. using g++. L-value: “l-value” refers to memory location which identifies. That's to protect people from changing the values of temporaries that are destroyed before their new value can be used . Now an lvalue reference is a reference that binds to an lvalue. g. First the compiler performs an implicit array-to-pointer conversion for "abc", so the type of "abc" becomes const char*. This is why you will see the C++ library provide what appears to be a single template, that works in both lvalue and rvalue contexts. Thus, both a rvalue and another value can be assigned to values. Add a comment. If you really want to or need to specify the parameters, you can use std::move to convert an lvalue to an rvalue at the calling site. lval]/3. " Use std::move if you want the former to work. If I change func (unsigned int&) to func (Color&), compiler accept it. The rules were reportedly designed. 4. Assignment to an rvalue doesn't really make sense, so it should be forbidden. The return of a new is a prvalue not an lvalue, because you cannot write: new T (arg) =. That works well with normal variables but uint8Vect_t(dataBlock. 4 — Lvalue references to const. Let’s turn it around a bit. Lvalue-to-rvalue conversion. 2k 9 128 212 asked Jan 14, 2016 at 8:26 Simon X. It could be an rvalue of course, but it doesn't have to be. In the previous question, I asked how this code should work: void f (const std::string &); //less efficient void f (std::string &&); //more efficient void g (const char * arg) { f (arg); } It seems that the move overload should probably be called because of the. c++ base constructor lvalue to parameter. ). 3. 3 -- Lvalue references ), we discussed how an lvalue reference can only bind to a modifiable lvalue. 45. They are declared using the ‘&’ before the name of the variable. A pointer is not the kind of thing that can be an rvalue or an lvalue. int rVal () { return 0; }. The "l" and "r" in "lvalue reference" and "rvalue reference" refers to the categories of values to which the reference can bind, not to the category of the id-expression naming a variable of this reference type. But due to the the existence of std::vector::push_back(value_type const & val), which copies and would be the overriding call, I need to convert the lvalue object to an rvalue. In return w, the implicitly movable entity w is treated as an rvalue when the return type of the function is RRefTaker as in example three, but it is treated as an lvalue when the return type of the function is Widget && as in example four. 10): An lvalue (so called, historically, because lvalues could appear on the left-hand side of an assignment expression) designates a function or an object. However, rvalues can't be converted to lvalues. There are no references of references in C++. One could also say that an rvalue is any expression that is not an lvalue . Hot Network QuestionsSorted by: 19. I'm not sure if this is the root of the issue but here's MSVC's implementation of std::array -related constructors of std::span . Lvaluesand Rvalues Lvalues and rvalues aren’t really language features. It's not an rvalue reference, but a forwarding reference; which could preserve the value category of the argument. For example second type of the pair should be std::string, not const std::string * and all your problems would go away. const A& ), and lvalue-to-rvalue conversion is suppressed when binding lvalue-reference. Second (and you probably missed that), const char* is converted to a rvalue std::string via the const char* non-explicit constructor of std::string (# 5 in the link). e. std::forward is a conditional std::move. it is a reference only to rvalues. An lvalue (pronounced “ell-value”, short for “left value” or “locator value”, and sometimes written as “l-value”) is an expression that evaluates to an identifiable object or function (or bit-field). The reason why you need to const is to make x not a forwarding reference. An example of an rvalue would be a literal constant – something like ’8′, or ’3. This example might clarify it: 16. And an rvalue reference is a reference that binds to an rvalue. Among. During reference initialization, where the reference to cv1 T is bound to the lvalue or rvalue result of a conversion from the initializer expression from the class type cv2 S,. A void * value resulting from such a conversion can be converted back to the original function. Open the project's Property Pages dialog box. Recall that there is a difference between the concept of an Lvalue and an Rvalue. The choice of copy or move constructor only occurs when passing an object by value. A pointer is a type. According to the rule of forwarding reference, when an lvalue is passed to add, the template type argument Element will be deduced as SomeClass&. Lvalue to rvalue conversion changes the value category of an expression, without changing its type. Therefore, I will not jump right in and explain what rvalue references are. 右值 (rvalue, right value) ,右边的值,是指表达式结束后就不再存在的临时对象。. An lvalue is an expression that designates (refers to) an object. 2 Answers. According to the C++ specifications, it takes two rvalues as arguments and returns an rvalue. 8. enum type init and assignment must be enum inside,so enum type can't is lvalue。. test prep. The result is that of *reinterpret_cast<T2*>(p), where p is a pointer of type “pointer to T1 ” to the object designated by expression. When you use "Hello, World" in a context in which it is implicitly converted to a const char* pointing to its initial element, the resulting pointer is an rvalue (because it is a temporary object resulting from an implicit. e. The returned lvalue will contain exactly the result it is supposed to. Therefore, in the third line, they undergo an implicit lvalue-to-rvalue conversion. The following table lists exceptions to this rule. Using our understanding of. Whether it’s heap or stack, and it’s addressable. about undefined behaviorIf T is a reference an lvalue-reference type, the result is an lvalue; otherwise, the result is an rvalue and the lvalue-to-rvalue (conv. You might want to use it more than once in your constructor, so it shouldn't be moved from on first use unless you explicitly want to. That means you can't call non-const functions on the object, but if you want to pass rvalues such as temporaries, then calling non-const functions wouldn't necesarily make much sense anyway. The question related to this one. Being an lvalue or an rvalue is a property of an expression; that is, every expression is either an lvalue or an rvalue. 2), an xvalue if T is an rvalue reference to object type. lvalue and rvalue as function parameters. You must explicitly use std::move (or a cast) to convert an lvalue into an rvalue reference, and an rvalue reference will never bind to an lvalue on its own. We can take the address of an lvalue, but not of an rvalue. Conversely, d = static_cast<float> (j)/v; produces an. There are two common ways to get an xvalue expression: Use std::move to move an object. But for the third case i. Done. The reason is simple; named rvalue reference is treated as lvalue (and implicit conversion from lvalue to rvalue reference is forbidden by standard). You are comparing two different things that are not really related. Each expression has some non-reference type, and each expression belongs to exactly one of the three primary value categories: xvalue, and lvalue . An lvalue is an expression that yields an object reference, such as a variable name, an array. An rvalue is any expression that isn't an lvalue. So I know why the compiler is complaining (because of trying to bind rvalue to lvalue reference -- at least this is what I think is happening -- please correct me if I am wrong). Don't mix the two patterns. Once a move constructor is called upon the reference, the original object should be reset to the origin state, and so does any reference to it. 2, and 4. std::function's type is defined only by its target's signature(eg: void(int)) and std::function itself is defined by the. (I found that via this StackOverflow question: Rvalues in C++03 ) Here's a demo of this working at run-time. Rvalue references enable you to distinguish an lvalue from an rvalue. 3. It can appear only on the right-hand side of the assignment operator. Return lvalue reference from temporary object. Although the syntax of a compound literal is similar to a cast, the important distinction is that a cast is a non-lvalue. If T is an lvalue reference type or an rvalue reference to function type, the result is an lvalue; if T is an rvalue reference to object type, the result is an xvalue; otherwise, the result is a prvalue. Explicitly call a single-argument constructor or a conversion operator. You do pass an rvalue to some_function - but at the same time you create an argument rvalue_ref which is now an lvalue (so you can actually call the. No temporary is created, no copy is made, no constructors or. Forwarding references are very greedy, and if you don't pass in the exact same type (including. Oct 31, 2016 at 20:29. There are operators that yield lvalues: for example, if E is an expression of pointer type, then *E is an lvalue expression referring to the object to which E points. Thus, this syntax is now legal: T&& r = T(); rvalue references primarily provide for the following: Move semantics. This isn't strictly true in all cases; in unevaluated. Applying the lvalue-to-rvalue conversion to x reads the value of the mutable global variable globx, which makes it not a constant expression as the value of globx is subject to change (and, even if it were const, there would be the issue of its value not being known at compile time). 10) of a non-function, non-array type T can be converted to a prvalue. This allows you to explicitly move from an lvalue, using move to. Therefore, I thought of providing some macro/function that wraps a parameter so it can be passed whether it's an l/rvalue - in this case get_addr. 1 Answer. 1. 11 for the exact listing what the cast can do; what that section doesn't list, it can't do. References. The term “identity” is used by the C++ standard, but is not well-defined. end()) is a temporary object and cannot be bound to lvalue reference. It is really about rvalues vs. This is because, in C programming, characters are internally stored as integer values known as ASCII Values. It can be useful if I am writing a function which expects either an lvalue or rvalue in a parameter and wants to pass it to another function. In C++, the cast result belongs to one of the following value categories:. ConclusionFrom expr. I. The expressions f (), f (). ; If type is an rvalue reference to an object type, the cast result is an xvalue. In the previous question, I asked how this code should work: void f (const std::string &); //less efficient void f (std::string &&); //more efficient void g (const char * arg) { f (arg); } It seems that the move overload should probably be called because of the. rvalue references are marked with two ampersands (&&). It was introduced specifically to allow temporary streams to be usable without resorting to tricks. However, a (prvalue) rvalue cannot be converted implicitly to an lvalue or xvalue, except by user-defined conversions. The expression 0 is. The third constructor is called move constructor. An identifier that refers to an object is an lvalue, but an. std::move() is a function used to convert an lvalue reference into the rvalue reference. 255 How come a non-const reference cannot bind to a temporary object? 1 Why the code doesn't work on CodeBlocks,but on. As for why the compile fails when you omit the move: When Stream& operator<< (Stream& s, Dummy) is called without the move, Stream will be std::fstream. In the introduction to "Effective Modern C++" it says: A useful heuristic to determine whether an expression is an lvalue is to ask if you can take its address. I guess you are reading the Rvalue References: C++0x Features in VC10, Part 2. having an address). Lvalues and xvalues can be of incomplete types, but (prvalue) rvalues must be of complete types or void types. An lvalue may get converted to an rvalue: that's something perfectly legit and it happens quite often. Here is a silly code that doesn't compile: int x; 1 = x; // error: expression must be a modifyable lvalue. e. My guess is that this restriction has historical roots in the C++98 standard where rvalues were limited to temporaries, that were fully managed by the compiler. Regarding the second question. Here's why. cast (this is applicable from C++11 and later). 1) Is actually not so arbitrary. 5, then the R-value is 2. lvalues and rvalues are expression categories, not flavours of object. 1. But one important rule is that: one can. The answer is: yes, we do. "lvalues are named variables and rvalues are temporaries" is a good enough heuristic for a beginner, and no more an "oversimplification" than "I before E except after C" is for English. e. References in C++ are nothing but the alternative to the already existing variable. Once an entity has a name, it is clearly an lvalue! If you have a name for an rvalue reference, the entity with the name is not an rvalue but an lvalue. 1. fstream file{"filename"}; print_stream(file);I would like to write a variadic template function that accepts rvalues and lvalue references. Forwarding referece works with both lvalues and rvalues, with the help of template argument deduction. Or the compiler could convert said references to pointers, push a pointer on the stack, pop the identical pointer off, and call it std::move. Is there a way to write a function in C++ that accepts both lvalue and rvalue arguments, without making it a template? For example, suppose I write a function print_stream that reads from an istream and prints the data that was read to the screen, or something. Even if the variable's type is rvalue reference, the expression consisting of its name is an lvalue expression; vector has two overloads of assignment operator, one for Lvalue reference. " What this is saying in layman's terms is that you can't (and shouldn't) store an address reference to an rvalue. The quote doesn't say anything about the result of &, which in fact is an rvalue. ) is characterized by two independent properties: a . baz(1) by itself is not UB, but it would be UB to dereference the resulting pointer after the end of the full-expression containing baz(1). Enums are different in C and C++, for example, if someColor is enum, 'someColor = 1' is legal C, but not C++. And most implementations do that. and includes the following bullet which the examle belongs to: the evaluation of e results in the evaluation of a member ex of the set of potential results of e, and ex names a variable x that is not odr-used by ex (3. You can disable this behaviour with the /Za (disable language extensions) compiler switch under. Used to move the resources from a source object i. Use const Type& when you don't need to change or copy the argument at all, use pass-by-value when you want a modifiable value but don't care how you get it, and use Type& and Type&&. ) In very broad and simple terms, an lvalue refers to. However once the const keyword was added to the C++, lvalues were split into —. From a user's perspective, the meaning of it is that std::forward is a conditional cast to an rvalue. e. Like this: template <typename T> void foo (T &&value) { f (std::forward<T> (value)); } Here, T &&value is called a forwarding reference (as long T is deduced by the compiler. "Hello, World" is not of type const char*. If we have a lvalue we can return it from a function, so we get a rvalue. Unless encountered in unevaluated context (in an operand of sizeof, typeid, noexcept, or decltype), this conversion effectively copy-constructs a temporary object of type T using the original glvalue as the. The && syntax is either referring to a rvalue-reference or a universal-reference. lvalue references are marked with one ampersand (&). You can also convert any. I don't really understand why an rvalue and a non-modifiable lvalue would be the same. template <typename T> StreamWriter& StreamWriter::operator<< (const T& source) { Write (&source); return *this; } Share. In any assignment statement “lvalue” must have the capability to store the data. h and move. Hence, the end result is the attempted binding of the rvalue. As we've seen earlier, a and b are both lvalues. Example: Certain kinds of expressions involving rvalue references (8. I expect that when using a temporary instance of a Wraper object, the conversion operator defined for rvalue will always be used. If t returns by lvalue reference, the code does not compile because a rvalue reference cannot bind to it. return 17;} int m=func2(); // C++03-style copying. ref], a reference can be bound directly to the result of applying a conversion function to an initializer expression. However, you don't have double && in your code, you have U && for a deduced U. a non-const reference). init.