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

2015-05-06 19:37:17 +08:00
 linux40

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,格式好像有点乱啊,不想看别看了。。。×/

912 次点击
所在节点    C
6 条回复
sablib
2015-05-06 19:47:03 +08:00
= = 代码被当成 markdown了。。
linux40
2015-05-06 20:07:03 +08:00
@sablib 只有默认和markdown啊。。。
我是直接托的代码啊。。。
sablib
2015-05-06 21:54:00 +08:00
@linux40 可以用gist
linux40
2015-05-06 22:56:55 +08:00
@sablib 3q
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
2015-05-07 09:08:43 +08:00
@comicfans44 谢谢,知道了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/188996

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX