V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
linux40
V2EX  ›  C

一个关于 c++的初始化列表( 17 行)问题?

  •  
  •   linux40 · 2015-05-06 19:37:17 +08:00 · 932 次点击
    这是一个创建于 3518 天前的主题,其中的信息可能已经有所发展或是发生改变。

    ifndef STRBLOB_H

    define STRBLOB_H

    include <string>

    include <memory>

    include <vector>

    include <exception>

    include <initializer_list>

    class StrBlobPtr;
    class const_StrBlobPtr;
    class StrBlob
    {
    friend class StrBlobPtr;
    friend class const_StrBlobPtr;
    public:
    typedef std::vector<std::string>::size_type size_type;
    StrBlob(std::initializer_list<std::string> il)://这里为什么不能是引用?
    data(std::make_shared<std::vector<std::string>>(il)) {}
    StrBlob(): data(std::make_shared<std::vector<std::string>>()) {}

    std::string &front()
    {
        check(0, "front on empty StrBlob");
        return data->front();
    }
    const std::string &front() const
    {
        check(0, "front on empty StrBlob");
        return data->front();
    }
    std::string &back()
    {
        check(0, "back on empty StrBlob");
        return data->back();
    }
    const std::string &back() const
    {
        check(0, "back on empty StrBlob");
        return data->back();
    }
    size_type size() const { return data->size(); }
    bool empty() const { return data->empty(); }
    void push_back(const std::string &s) { data->push_back(s); }
    void pop_back() { data->pop_back(); }
    StrBlobPtr begin();
    StrBlobPtr end();
    const_StrBlobPtr begin() const;
    const_StrBlobPtr end() const;
    const_StrBlobPtr cbegin() const;
    const_StrBlobPtr cend() const;
    

    private:
    std::shared_ptr<std::vector<std::string>> data;
    void check(size_type i, const std::string &msg) const
    { if (i >= size()) throw std::out_of_range(msg); }
    };

    class StrBlobPtr
    {
    public:
    StrBlobPtr(StrBlob &sb, StrBlob::size_type sz = 0):
    wptr(sb.data), curr(sz) {}
    StrBlobPtr(): curr(0) {}

    std::string &deref() const
    {
        return (*check(curr, "dereference past end"))[curr];
    }
    StrBlobPtr &incr()
    {
        check(curr, "increment past end of StrBoldPtr");
        ++curr;
        return *this;
    }
    bool compare(const StrBlobPtr &sp)
        {return (wptr.lock() == sp.wptr.lock())&&(curr == sp.curr); }
    

    private:
    std::shared_ptr<std::vector<std::string>>
    check(StrBlob::size_type pos, const std::string &msg) const
    {
    auto ret = wptr.lock();
    if (!ret)
    throw std::runtime_error("unbound StrBlobPtr");
    if (pos >= ret->size())
    throw std::out_of_range(msg);
    return ret;
    }
    std::weak_ptr<std::vector<std::string>> wptr;
    StrBlob::size_type curr;
    };

    class const_StrBlobPtr
    {
    public:
    const_StrBlobPtr(const StrBlob &sb, StrBlob::size_type sz = 0):
    wptr(sb.data), curr(sz) {}
    const_StrBlobPtr(): curr(0) {}

    const std::string &deref() const
    {
        return (*check(curr, "dereference past end"))[curr];
    }
    const_StrBlobPtr &incr()
    {
        check(curr, "increment past end of StrBoldPtr");
        ++curr;
        return *this;
    }
    bool compare(const const_StrBlobPtr &sp) const
        {return (wptr.lock() == sp.wptr.lock())&&(curr == sp.curr); }
    

    private:
    std::shared_ptr<const std::vector<std::string>>
    check(StrBlob::size_type pos, const std::string &msg) const
    {
    auto ret = wptr.lock();
    if (!ret)
    throw std::runtime_error("unbound StrBlobPtr");
    if (pos >= ret->size())
    throw std::out_of_range(msg);
    return ret;
    }
    std::weak_ptr<const std::vector<std::string>> wptr;
    StrBlob::size_type curr;
    };

    inline StrBlobPtr StrBlob::begin() { return StrBlobPtr(*this); }
    inline StrBlobPtr StrBlob::end() { return StrBlobPtr(*this, size()); }
    inline const_StrBlobPtr StrBlob::begin() const
    { return const_StrBlobPtr(*this); }

    inline const_StrBlobPtr StrBlob::end() const
    { return const_StrBlobPtr(*this, size()); }

    inline const_StrBlobPtr StrBlob::cbegin() const
    { return const_StrBlobPtr(*this); }

    inline const_StrBlobPtr StrBlob::cend() const
    { return const_StrBlobPtr(*this, size()); }

    endif // STRBLOB_H

    /×顺便大家吐槽一下有没有什么改进的地方,其实就是cpp_primer的练习12.22,格式好像有点乱啊,不想看别看了。。。×/

    第 1 条附言  ·  2015-05-06 22:54:31 +08:00
    UPDATE:https://gist.github.com/c3a14f6c8b10a83ece3c.git
    第 2 条附言  ·  2015-05-06 22:55:20 +08:00
    17行那里为什么不能是引用?
    第 3 条附言  ·  2015-05-06 22:56:20 +08:00
    6 条回复    2015-05-07 09:08:43 +08:00
    sablib
        1
    sablib  
       2015-05-06 19:47:03 +08:00
    = = 代码被当成 markdown了。。
    linux40
        2
    linux40  
    OP
       2015-05-06 20:07:03 +08:00
    @sablib 只有默认和markdown啊。。。
    我是直接托的代码啊。。。
    sablib
        3
    sablib  
       2015-05-06 21:54:00 +08:00
    @linux40 可以用gist
    linux40
        4
    linux40  
    OP
       2015-05-06 22:56:55 +08:00
    @sablib 3q
    comicfans44
        5
    comicfans44  
       2015-05-07 07:55:52 +08:00
    根据http://en.cppreference.com/w/cpp/utility/initializer_list的说明
    since c++14:
    The underlying array is a temporary array, in which each element is copy-initialized (except that narrowing conversions are invalid) from the corresponding element of the original initializer list. The lifetime of the underlying array is the same as any other temporary object, except that initializing an initializer_list object from the array extends the lifetime of the array exactly like binding a reference to a temporary (with the same exceptions, such as for initializing a non-static class member). The underlying array may be allocated in read-only memory.

    因为是临时对象,所以不能用引用。

    但const 引用是可以的,与传值效果相同,因为initializer_list的拷贝不会进行内部元素的拷贝,这一点可参考c++标准18.9
    An object of type initializer_list<E> provides access to an array of objects of type const E. [ Note:
    A pair of pointers or a pointer plus a length would be obvious representations for initializer_list.
    initializer_list is used to implement initializer lists as specified in 8.5.4. Copying an initializer list does
    not copy the underlying elements. — end note ]
    linux40
        6
    linux40  
    OP
       2015-05-07 09:08:43 +08:00
    @comicfans44 谢谢,知道了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2970 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 13:18 · PVG 21:18 · LAX 05:18 · JFK 08:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.