[c++11]range-for中的observing、modifying、proxy iterators

range-for[c++11]

What is the correct way of using C++11’s range-based for?
What syntax should be used? for (auto elem : container), or for (auto& elem : container) or for (const auto& elem : container)? Or some other?

答案直接在Generic code 部分。
下面是解释:

There’re some difference between observing the elements in the continer vs. modifying them in place.

Observing

1. cheap-to-copy :by value

适用简单类型的元素,比如int,double

for (auto elem : container) 
eg1 for (auto x : v)

observing “int” in “vector”.

vector<int> v = {1, 3, 5, 7, 9};

for (auto x : v)
    cout << x << ' ';

output:

1 3 5 7 9

2.general case : by const reference

eg2 for (auto x : v)

复杂类型的by value(效率低,会调用拷贝构造。)

observing “customclass_type” in “vector”.

// A sample test class, with custom copy semantics.
class X
{
public:
    X() 
        : m_data(0) 
    {}

    X(int data)
        : m_data(data)
    {}

    ~X() 
    {}

    X(const X& other) 
        : m_data(other.m_data)
    { cout << "X copy ctor.\n"; }

    X& operator=(const X& other)
    {
        m_data = other.m_data;       
        cout << "X copy assign.\n";
        return *this;
    }

    int Get() const
    {
        return m_data;
    }

private:
    int m_data;
};

ostream& operator<<(ostream& os, const X& x)
{
    os << x.Get();
    return os;
}

vector<X> v = {1, 3, 5, 7, 9};

cout << "\nElements:\n";
for (auto x : v)
{
    cout << x << ' ';
}

output: 在vector<X>初始化时,拷贝构造函数被调用了。

Elements:
X copy ctor.
1 X copy ctor.
3 X copy ctor.
5 X copy ctor.
7 X copy ctor.
9

在range-based for loop iterations的时候,采用的是by value的方法,初始化容器中每个元素时,copy constructor 被调用了。这样做很低效,因为我们只想观察容器中的元素,而不是想拷贝一个临时对象。(e.g. if these elements are instances of std::string, heap memory allocations can be done, with expensive trips to the memory manager, etc.)

eg3 for (const auto& x : v)

所以最好的观测方法是常量引用传递const auto &

vector<X> v = {1, 3, 5, 7, 9};

cout << "\nElements:\n";
for (const auto& x : v)
{ 
    cout << x << ' ';
}

output:没有拷贝构造函数调用。更加高效。

Elements:
1 3 5 7 9

Modifying

如果要修改容器中的元素, for (auto elem : container)或者for (const auto& elem : container)的写法是错误的。

eg4 for (auto elem : container)

修改的是拷贝局部临时变量的值,不是原始数据

vector<int> v = {1, 3, 5, 7, 9};
for (auto x : v)  // <-- capture by value (copy)
    x *= 10;      // <-- a local temporary copy ("x") is modified,
                  //     *not* the original vector element.

for (auto x : v)
    cout << x << ' ';

output

1 3 5 7 9
eg5 for (const auto& elem : container)

修改常量引用会导致编译不通过

TestRangeFor.cpp:138:11: error: assignment of read-only reference 'x'
          x *= 10;
            ^
eg6 for (auto& x : v)

正确方法是非常量引用

vector<string> v = {"Bob", "Jeff", "Connie"};

// Modify elements in place: use "auto &"
for (auto& x : v)
    x = "Hi " + x + "!";

// Output elements (*observing* --> use "const auto&")
for (const auto& x : v)
    cout << x << ' ';

output

Hi Bob! Hi Jeff! Hi Connie!

Case of Proxy Iterator

需求:想通过非常量引用修改容器中bool的状态。

eg7 for (auto& x : v)
vector<bool> v = {true, false, false, true};
for (auto& x : v)
    x = !x;

编译不通过

TestRangeFor.cpp:168:20: error: invalid initialization of non-const reference of
 type 'std::_Bit_reference&' from an rvalue of type 'std::_Bit_iterator::referen
ce {aka std::_Bit_reference}'
     for (auto& x : v)
                    ^

bool特化的std::vector模板,是由把bool打包优化空间后实现的,每个boolean值占1bit,8个boolean才占1byte。
因为不能返回一个单独的bit的reference,所以vector<bool>使用了一个proxy iterator设计模式。
proxy iterator在解引用的时候,不产生普通的bool&,而是返回(by value)一个临时对象,这个对象是一个可以表达boolproxy class

REF:

The problem is that std::vector template is specialized for bool, with an implementation that packs the bools to optimize space (each boolean value is stored in one bit, eight “boolean” bits in a byte).

Because of that (since it’s not possible to return a reference to a single bit), vector uses a so called “proxy iterator” pattern. A “proxy iterator” is an iterator that, when dereferenced, does not yield an ordinary bool &, but instead returns (by value) a temporary object, which is a proxy class convertible to bool. (See also this question and related answers here on StackOverflow.)

eg8 for (auto&& x : v)
vector<bool> v = {true, false, false, true};

// Invert boolean status
for (auto&& x : v)  // <-- note use of "auto&&" for proxy iterators
    x = !x;

// Print new element values
cout << boolalpha;        
for (const auto& x : v)// 遵从observing的const auto&
    cout << x << ' ';

output

false true true false
  • proxy iterators也遵从observing的for (const auto& elem : container)
  • for (auto&& elem : container)也适用ordinary (non-proxy) iterators,比如vector<int>或者vector<string>

Summary

  • If the objects are cheap to copy (like ints, doubles, etc.) OR NEED to make a local copy.
for (auto elem : container)    // capture by value
  • For observing the complex elements (not need to copy)
for (const auto& elem : container)    // capture by const reference
  • For modifying the elements in place
for (auto& elem : container)    // capture by (non-const) reference
  • If the container uses “proxy iterators” (like std::vector<bool>)
for (auto&& elem : container)    // capture by &&

Generic code

  • For observing the elements
for (const auto& elem : container)    // capture by const reference
  • For modifying the elements in place
for (auto&& elem : container)    // capture by &&
Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计,皆可应用在项目、毕业设计、课程设计、期末/期/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值