Passing to a Reference Argument by Value

前端 未结 7 919
名媛妹妹
名媛妹妹 2021-01-17 14:40

Consider this simple program:

vector foo = {0, 42, 0, 42, 0, 42};
replace(begin(foo), end(foo), foo.front(), 13);

for(const auto& i : foo) co         


        
相关标签:
7条回答
  • 2021-01-17 15:14

    You can convert the given value into an rvalue to achieve the desired effect. The example below works, without defining any extra functions, simply by adding zero to the value.

    vector<int> foo = {0, 42, 0, 42, 0, 42};
    replace(begin(foo), end(foo), foo.front()+0, 13);
    
    for(const auto& i : foo) cout << i << '\t';
    

    Or even (as suggested by Jarod42) just the unary + operator, which is a no-op:

    vector<int> foo = {0, 42, 0, 42, 0, 42};
    replace(begin(foo), end(foo), +foo.front(), 13);
    
    for(const auto& i : foo) cout << i << '\t';
    

    Obviously either of these still create a temporary. I don't think you can get away from that.

    0 讨论(0)
  • 2021-01-17 15:16

    To be more explicit you can use int() as a constructor to create a temporary:

    replace(begin(foo), end(foo), int(foo.front()), 13);
    

    Instead of adding a value. See Demo.

    0 讨论(0)
  • 2021-01-17 15:24

    You can write a simple function that takes in a reference and returns a value. this will "convert" the reference into a value. This does generate a temporary but it is unnamed and will be destroyed at the end of the full expression. Something like

    template<typename T>
    T value(const T& ref)
    {
        return ref;
    }
    

    And then you can use it like

    int main()                                                   
    {                                                            
        vector<int> foo = {0, 42, 0, 42, 0, 42};
        replace(begin(foo), end(foo), value(foo.front()), 13);
    
        for(const auto& i : foo) cout << i << '\t';                                      
    }
    

    output:

    13  42  13  42  13  42
    

    Live Example

    0 讨论(0)
  • 2021-01-17 15:25
    vector<int> foo = {0, 42, 0, 42, 0, 42};
    replace(begin(foo), end(foo), static_cast<int>(foo.front()), 13);
    assert(equal(begin(foo), end(foo), begin({13, 42, 13, 42, 13, 42})));
    
    0 讨论(0)
  • 2021-01-17 15:31

    A solution could be as follows (even though you are making a temporary)

    template<class T>
    void replace_value_of_first(std::vector<T>& v, const T& value)
    {
        std::replace(v.begin(), v.end(), T(v.front()), value);
    }
    
    0 讨论(0)
  • 2021-01-17 15:31

    In this particular case (when the old value is the first of the vector), you can reverse the order of substitution with rbegin() and rend().

    In general, I don't know if it's possible, in a simple way, without make a copy.

    int main ()
     {
       std::vector<int> foo = {0, 42, 0, 42, 0, 42};
       std::replace(foo.rbegin(), foo.rend(), foo.front(), 13);
    
       for(const auto & i : foo)
          std::cout << i << '\t';
    
       std::cout << std::endl;
    
       return 0;
     }
    

    p.s.: sorry for my bad English.

    0 讨论(0)
提交回复
热议问题