C++ Type and Value Category for Expression and Variable

前端 未结 3 536
死守一世寂寞
死守一世寂寞 2021-02-06 01:31

From this link, it says that

Objects, references, functions including function template specializations, and expressions have a property called type

<
3条回答
  •  栀梦
    栀梦 (楼主)
    2021-02-06 02:21

    Based on this each function call is an expression. Each argument passed to the function is also an expression.

    Therefore, when you make a call to SumFunc(rf_int); you create an expression from the single rf_int variable.

    ISO/IEC 14882 (c++14 standard) states that "The expression designates the object or function denoted by the reference, and the expression is an lvalue or an xvalue, depending on the expression."

    Thus, the rf_int expression will be of type int.

    This comment (you mention it before) is about type conversion error.

    To illustrate my explanation, I have prepared a more complex, but (hopefully) more understandable example. This example is about why we need rvalue refernce type and how to use it correctly.

    class Obj {
        int* pvalue;
    public:
        Obj(int m) {
            pvalue = new int[100];
            for(int i = 0; i < 100; i++)
                pvalue[i] = m + i;
        }
        Obj(Obj& o) {  // copy constructor
            pvalue = new int[100];
            for(int i = 0; i < 100; i++)
                pvalue[i] = o.pvalue[i];
        }
        Obj(Obj&& o) {  // move constructor
            for(int i = 0; i < 100; i++)
                pvalue = o.pvalue;
            o.pvalue = nullptr;
        }
       // ...
    };
    

    Example 1

      Obj obj1(3);
      Obj obj2(obj1);  // copy constructor
      Obj obj3(std::move(obj1)); // move constructor
      Obj obj4(Obj(3)); // move constructor
    

    Line #1 - obj1 created.
    Line #2 - obj2 created as a copy of obj1
    Line #3 - obj3 created by moving value of obj1 to the obj3; obj1 loose it's value
    Line #4 - temporary object created by Obj(3); obj4 created by moving value of temporary object to obj4; temporary object loose it's value

    I think we have no real need of int&& but Obj&& can be very useful. Especially in the line #4.

    Example 2 with my (simplified) interpretation of compiler errors

    void SomeFunc0(Obj   arg) {};
    void SomeFunc1(Obj&  arg) {};
    void SomeFunc2(Obj&& arg) {};
    
    int main()
    {
      Obj   obj1(3);        // object
      Obj&  obj2 = obj1;    // reference to the object
      Obj&& obj3 = Obj(3);  // reference to the temporary object with extened lifetime
    
    
        SomeFunc0(obj1); // ok - new object created from Obj
        SomeFunc0(obj2); // ok - new object created from Obj&
        SomeFunc0(obj3); // ok - new object created from Obj&&
        SomeFunc0(Obj(3)); // ok - new object created from temporary object
        SomeFunc0(std::move(obj1)); // ok - new object created from temporary object
        SomeFunc0(std::move(obj2)); // ok - new object created from temporary object
        SomeFunc0(std::move(obj3)); // ok - new object created from temporary object
    
        SomeFunc1(obj1); // ok - reference to obj1 passed
        SomeFunc1(obj2); // ok - reference to obj1 passed
        SomeFunc1(obj3); // ok - reference to temp. obj. passed
        SomeFunc1(Obj(3)); // error - lifetime of the temp. obj. too short
        SomeFunc1(std::move(obj1)); // error - lifetime of the temp. obj. too short
        SomeFunc1(std::move(obj2)); // error - lifetime of the temp. obj. too short
        SomeFunc1(std::move(obj3)); // error - lifetime of the temp. obj. too short
    
        SomeFunc2(obj1); // error - temporary object required
        SomeFunc2(obj2); // error - temporary object required
        SomeFunc2(obj3); // error - lifetime of the temp. obj. too long
        SomeFunc2(Obj(3)); // ok
        SomeFunc2(std::move(obj1)); // ok
        SomeFunc2(std::move(obj2)); // ok
        SomeFunc2(std::move(obj3)); // ok
    
        return 0;
    }
    

提交回复
热议问题