C++ function returning reference to array

后端 未结 5 1295
天命终不由人
天命终不由人 2021-01-04 08:47

Is there any other way to receive a reference to an array from function returning except using a pointer?

Here is my code.

int ia[] = {1, 2, 3};
decl         


        
相关标签:
5条回答
  • 2021-01-04 08:55

    Your functions signature would look like this:

    int(&A::adapter(/*input_args_or_empty*/))[3]{
       return ia;
    }
    
    0 讨论(0)
  • 2021-01-04 08:56

    Some alternatives I think are superior in C++14 onwards:

    auto and array reference trailing return type:

    template <typename T, std::size_t N>
    auto array_ref_test(T(&array)[N]) -> T(&)[N]
    {
        return array;
    }
    

    decltype(auto):

    template <typename T, std::size_t N>
    decltype(auto) array_ref_test(T(&array)[N])
    {
        return array;
    }
    

    Example usage:

    int array_ref_ [] = { 1, 2, 3, 4, 5 };   
    decltype(auto) array_ref_result = array_ref_test(array_ref_); //'decltype(auto)' preserves reference unlike 'auto'
    std::cout << std::size(array_ref_result);
    
    0 讨论(0)
  • 2021-01-04 09:03

    Is there any other way to receive a reference to an array from function returning except using a pointer?

    Yes, using a reference to an array, like with any other type:

    int (&ref)[3] = a.foo();
    

    To avoid the clunky syntax, you could use a typedef instead.

    typedef int int_array3[3];
    
    ...
    int_array3& foo() { return ia; }
    
    ...
    
    int_array3& ref = a.foo();
    
    0 讨论(0)
  • 2021-01-04 09:04

    You should use std::array to avoid confusion and make cleaner, safer and less clunky code:

    class A {
    public:
        typedef std::array<int,3> array;
        A() : ia{1, 2, 3} {}
        array &foo(){ return ia; }
    private:
        array ia;
    };
    
    int main() {
        A a;
        auto i1 = a.foo();      // ok, type of i1 is A::array, it is a copy and visit array by i1[0]
        for ( int i : i1 ) {}   // you can iterate now, with C array you cannot anymore
        auto &i2 = a.foo();     // ok, type of i2 is A::array&, you can change original by i2[0] = 123 
        A::array i3 = a.foo();  // fine, i3 is now a copy and visit array by i3[0]
        A::array &i4 = a.foo(); // fine, you can change original by i4[0] = 123
        int *i5 = a.foo().data();  // if you want old way to pass to c function for example, it is safer you explicitly show your intention
        return 0;
    }
    

    I know the name of the array is a pointer to the first element in that array

    This is incorrect, array can be implicitly converted to a pointer to the first element. It is not the same.

    0 讨论(0)
  • 2021-01-04 09:09

    To answer this question one can design a solution around std::reference_wrapper. This code compiles and runs.

    #pragma once
    #include <array>
    #include <functional>
    #include <cstdlib>
    #include <ctime>
    
    namespace {
    
    /// <summary>
    /// some generic utility function 
    /// with argument declared as 
    /// native array reference
    /// for testing purposes only
    /// </summary>
    template<typename T, std::size_t N >
    inline void array_util_function( T (&arr_ref) [N] ) {
        auto random = [](int max_val, int min_val = 1) -> int {
            // use current time as seed for 
            // random generator, but only once
            static auto initor = []() { 
                std::srand((unsigned)std::time(nullptr)); return 0; 
            }();
    
            return min_val + std::rand() / ((RAND_MAX + 1u) / max_val);
        };
    
        for (auto & element : arr_ref) {
            element = random(N);
        }
    }
    
    // the key abstraction
    template <typename T, std::size_t N>
    using native_arr_ref_wrapper = std::reference_wrapper<T[N]>;
    
    template<typename T, std::size_t N >
    constexpr std::size_t array_size(T(&arr_ref)[N]) {
        return N;
    }
    
    // return the size of the native array
    // contained within
    template<typename T, std::size_t N >
    constexpr std::size_t array_size(native_arr_ref_wrapper<T,N> & narw_) {
        return array_size(narw_.get());
    }
    
    /// <summary>
    /// returns std::reference_wrapper copy
    /// that contains reference to native array 
    /// in turn contained inside the std::array
    /// argument
    /// </summary>
    template<typename T, std::size_t N >
        inline auto
            native_arr_ref(const std::array<T, N> & std_arr)
            -> native_arr_ref_wrapper<T,N>
    {
        using nativarref = T(&)[N];
    
        return std::ref(
                (nativarref)*(std_arr.data())
            );
    }
    
        /// <summary>
        /// returns std::reference_wrapper copy
        /// that contains reference to native array 
        /// </summary>
        template<typename T, std::size_t N >
        inline auto
            native_arr_ref(const T (& native_arr)[N] )
            -> native_arr_ref_wrapper<T, N>
        {
            using nativarref = T(&)[N];
    
            return std::ref(
                (nativarref)*(native_arr)
            );
        }
    
        auto printarr = [](auto arr_ref, const char * prompt = "Array :") {
            printf("\n%s:\n{ ", prompt);
            int j = 0;
            // use the array reference 
            // to see the contents 
            for (const auto & element : arr_ref.get()) {
                printf(" %d:%d ", j++, element);
            }
            printf(" }\n");
        };
    
    // arf == native array reference
    void test_ () {
    
    using std::array;
    // the arf type is 
    // std::reference_wrapper<int[10]> 
    auto arf  = native_arr_ref(array<int, 10>{});
    // the arf type is same here 
    // but made from a native array
    auto ar2 = native_arr_ref({ 0,1,2,3,4,5,6,7,8,9 });
    printarr(ar2);
    
    // notice how argument to native_arr_ref()
    // does not exist here any more
    // but, wrapper contains the copy 
    // of the native array  
    
    // type is here: int[10]&
    auto & native_arr_ref = arf.get();
    
    // due to array type decay 
    // the type is here: int *
    auto native_arr_ptr = arf.get();
    
    // size_t
    const auto size = array_size(arf);
    
    // this function requires
    // native array as argument
    // this is how we use arf in place of 
    // native arrays
    array_util_function(arf.get());
    
    printarr(arf);
    
        }
      }
    
    0 讨论(0)
提交回复
热议问题