【问题标题】:Capture handle by reference or by value to class template ctor通过引用或值捕获句柄到类模板ctor
【发布时间】:2020-07-14 21:06:17
【问题描述】:

考虑一个模板类InputBuffer

template<class Source, size_t Capacity>
class InputBuffer
{
    public:
        explicit InputBuffer(Source src);

        int getchar();

    private:
        std::byte const* m_read_ptr;
        std::byte const* m_last_valid;
        Source m_src;
        std::array<std::byte, Capacity> m_data;

        void fetchAndResetPointers();
};

问题:构造函数是否应该接受src 作为引用并存储指针而不是按值获取? 非常调用者在这里期望引用语义。但是,也有可能Source 已经是某种指针,然后,通过引用获取src 并存储指针会导致不必要的间接。如果不通过引用传递,用户可以根据需要使用std::ref

【问题讨论】:

    标签: c++ templates pass-by-reference api-design


    【解决方案1】:

    在我看来,这个类并不好 - 你假设“源”需要 m_read_ptrm_last_validm_data 作为上下文。但是,如果它是一个文件,例如,它不需要这些。相反,将此类重写为接口,或者更好的是,根本不创建泛型类并在处理“源”时使用模板,例如伪代码:

    class FileBuffer {
    public:
      explicit FileBuffer(File* f) : m_f(f) {}
      int getchar() { return read(f, 1); }
    private:
      File* m_f;
    };
    
    template<class T>
    void print_from_buffer_to_stdout(T& buf) {
      std:: cout << buf.getchar();
    }
    
    int main() {
      FileBuffer f = get_file_buffer(); // somehow
      print_from_buffer_to_stdout(f);
    }
    

    【讨论】:

    • 其实m_read_ptr会指向本地缓冲区数组,fetchAndResetPointers会在buffer为空时调用(m_read_ptr == m_last_valid)。您的建议不是缓冲区:它依赖于 File 在内部提供缓冲区。使用 InputBuffer 的原因是调用 read 可能会产生很大的开销,因此您通常调用 read 来获取多个字节,例如一整页。
    • 你没有抓住重点——“inputbuffer”类不应该包含“Source”作为其成员,或者不包含所有其他成员/方法。
    • 抱歉,您确实需要了解如何实现缓冲 I/O。输入缓冲区的实现至少需要知道它的来源,如果它不是 getchar 的参数的话。但它不能作为 getchar 的参数,因为这会引入不一致。
    猜你喜欢
    • 2023-04-09
    • 2011-06-20
    • 2016-10-20
    • 2019-08-28
    • 1970-01-01
    • 2016-09-06
    • 2011-02-01
    • 1970-01-01
    相关资源
    最近更新 更多