LoginSignup
0
0

定数回ループを範囲forで

Last updated at Posted at 2024-05-25

単純増加のループ処理

C++03
for (int i = 0; i < 5; i++) {
  // ...
}

を範囲forにしたとき

C++11
for (auto i : range<int>(5)) {
  // ...
}

みたいな実行効率を考えた range クラス相当は既にあるだろうと思ったのですが、軽く検索すると int[] や vec などに [a] = a を代入してから使用しているものしか見つけられませんでした。真面目に探せば実行効率を考えたものは必ず出てくると思いますが、ざっくりと書いてみた。(コンパイラの最適化をかなり当てにしています)

sample.cpp
#include <iostream>

template <typename T>
struct range {
    struct iterator {
        T value;

        iterator(T n) : value(n) {}
        T operator *() { return value; }
        void operator ++() { ++value; }
        bool operator !=(iterator &rhs) { return value != rhs.value; }
    };

    T _start, _end;

    range(T count) : _start(0), _end(count) {}
    range(T start, T end) : _start(start), _end(end) {}
    iterator begin() { return iterator(_start); }
    iterator end() { return iterator(_end); }
};

int main()
{
    std::cout << "range(5):";
    for (const auto i : range<int>(5))
        std::cout << " " << i;
    std::cout << std::endl;

    std::cout << "range(2, 7):";
    for (const auto i : range<size_t>(2, 7))
        std::cout << " " << i;
    std::cout << std::endl;
}
実行結果
range(5): 0 1 2 3 4
range(2, 7): 2 3 4 5 6

Apple clang version 15.0.0 (clang-1500.3.9.4)[x86_64] を使い

$ clang++ -std=c++11 sample.cpp -O -S

で出力したアセンブラの一部を抜粋

range(5)のループ部
	xorl	%r14d, %r14d
	leaq	L_.str.1(%rip), %r15
	.p2align	4, 0x90
LBB0_1:                                 ## =>This Inner Loop Header: Depth=1
	movl	$1, %edx
	movq	%rbx, %rdi
	movq	%r15, %rsi
	callq	__ZNSt3__124__put_character_sequenceB8ue170006IcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_m
	movq	%rax, %rdi
	movl	%r14d, %esi
	callq	__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEi
	incl	%r14d
	cmpl	$5, %r14d
	jne	LBB0_1

変数 i は r14d レジスタで完結しています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0