Как использовать изменчивый вектор? - PullRequest
0 голосов
/ 12 марта 2019

Я хочу оценить, сколько времени занимает сортировка:

#include <vector>
#include <algorithm>
using namespace std;

int main()
{
    int n = 100000000;
    volatile vector<volatile int> vec; vec.reserve(n);
    for(int nn = n; nn > 0; nn--) vec.push_back(nn);
    sort(vec.begin(), vec.end());
}

AFAIK переменная здесь необходима, потому что в противном случае компилятор был бы свободен оптимизировать записи в этот vector, потому что написанное никогда не используется. Так что никакой сортировки на самом деле не будет.

Однако, по-видимому, это не сработает:

wtf.cc: In function ‘int main()’:
wtf.cc:8:50: error: passing ‘volatile std::vector<volatile int>’ as ‘this’ argument discards qualifiers [-fpermissive]
  volatile vector<volatile int> vec; vec.reserve(n);
                                                  ^
In file included from /usr/include/c++/7/vector:69:0,
                 from wtf.cc:1:
/usr/include/c++/7/bits/vector.tcc:65:5: note:   in call to ‘void std::vector<_Tp, _Alloc>::reserve(std::vector<_Tp, _Alloc>::size_type) [with _Tp = volatile int; _Alloc = std::allocator<volatile int>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’
     vector<_Tp, _Alloc>::
     ^~~~~~~~~~~~~~~~~~~
wtf.cc:9:48: error: passing ‘volatile std::vector<volatile int>’ as ‘this’ argument discards qualifiers [-fpermissive]
  for(int nn = n; nn > 0; nn--) vec.push_back(nn);
                                                ^
In file included from /usr/include/c++/7/vector:64:0,
                 from wtf.cc:1:
/usr/include/c++/7/bits/stl_vector.h:939:7: note:   in call to ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = volatile int; _Alloc = std::allocator<volatile int>; std::vector<_Tp, _Alloc>::value_type = volatile int]’
       push_back(const value_type& __x)
       ^~~~~~~~~
wtf.cc:10:17: error: passing ‘volatile std::vector<volatile int>’ as ‘this’ argument discards qualifiers [-fpermissive]
  sort(vec.begin(), vec.end());
                 ^
In file included from /usr/include/c++/7/vector:64:0,
                 from wtf.cc:1:
/usr/include/c++/7/bits/stl_vector.h:563:7: note:   in call to ‘std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::begin() [with _Tp = volatile int; _Alloc = std::allocator<volatile int>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<volatile int*, std::vector<volatile int> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = volatile int*]’
       begin() _GLIBCXX_NOEXCEPT
       ^~~~~
wtf.cc:10:28: error: passing ‘volatile std::vector<volatile int>’ as ‘this’ argument discards qualifiers [-fpermissive]
  sort(vec.begin(), vec.end());
                            ^
In file included from /usr/include/c++/7/vector:64:0,
                 from wtf.cc:1:
/usr/include/c++/7/bits/stl_vector.h:581:7: note:   in call to ‘std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::end() [with _Tp = volatile int; _Alloc = std::allocator<volatile int>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<volatile int*, std::vector<volatile int> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = volatile int*]’
       end() _GLIBCXX_NOEXCEPT
       ^~~
In file included from /usr/include/x86_64-linux-gnu/c++/7/bits/c++allocator.h:33:0,
                 from /usr/include/c++/7/bits/allocator.h:46,
                 from /usr/include/c++/7/vector:61,
                 from wtf.cc:1:
/usr/include/c++/7/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::deallocate(__gnu_cxx::new_allocator<_Tp>::pointer, __gnu_cxx::new_allocator<_Tp>::size_type) [with _Tp = volatile int; __gnu_cxx::new_allocator<_Tp>::pointer = volatile int*; __gnu_cxx::new_allocator<_Tp>::size_type = long unsigned int]’:
/usr/include/c++/7/bits/alloc_traits.h:462:9:   required from ‘static void std::allocator_traits<std::allocator<_Tp1> >::deallocate(std::allocator_traits<std::allocator<_Tp1> >::allocator_type&, std::allocator_traits<std::allocator<_Tp1> >::pointer, std::allocator_traits<std::allocator<_Tp1> >::size_type) [with _Tp = volatile int; std::allocator_traits<std::allocator<_Tp1> >::allocator_type = std::allocator<volatile int>; std::allocator_traits<std::allocator<_Tp1> >::pointer = volatile int*; std::allocator_traits<std::allocator<_Tp1> >::size_type = long unsigned int]’
/usr/include/c++/7/bits/stl_vector.h:180:19:   required from ‘void std::_Vector_base<_Tp, _Alloc>::_M_deallocate(std::_Vector_base<_Tp, _Alloc>::pointer, std::size_t) [with _Tp = volatile int; _Alloc = std::allocator<volatile int>; std::_Vector_base<_Tp, _Alloc>::pointer = volatile int*; std::size_t = long unsigned int]’
/usr/include/c++/7/bits/vector.tcc:78:17:   required from ‘void std::vector<_Tp, _Alloc>::reserve(std::vector<_Tp, _Alloc>::size_type) [with _Tp = volatile int; _Alloc = std::allocator<volatile int>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’
wtf.cc:8:50:   required from here
/usr/include/c++/7/ext/new_allocator.h:125:19: error: invalid conversion from ‘volatile void*’ to ‘void*’ [-fpermissive]
  ::operator delete(__p);
  ~~~~~~~~~~~~~~~~~^~~~~
In file included from /usr/include/c++/7/ext/new_allocator.h:33:0,
                 from /usr/include/x86_64-linux-gnu/c++/7/bits/c++allocator.h:33,
                 from /usr/include/c++/7/bits/allocator.h:46,
                 from /usr/include/c++/7/vector:61,
                 from wtf.cc:1:
/usr/include/c++/7/new:124:6: note:   initializing argument 1 of ‘void operator delete(void*)’
 void operator delete(void*) _GLIBCXX_USE_NOEXCEPT
      ^~~~~~~~
In file included from /usr/include/c++/7/vector:60:0,
                 from wtf.cc:1:
/usr/include/c++/7/bits/stl_algobase.h: In instantiation of ‘static _Tp* std::__copy_move_backward<_IsMove, true, std::random_access_iterator_tag>::__copy_move_b(const _Tp*, const _Tp*, _Tp*) [with _Tp = volatile int; bool _IsMove = true]’:
/usr/include/c++/7/bits/stl_algobase.h:588:58:   required from ‘_BI2 std::__copy_move_backward_a(_BI1, _BI1, _BI2) [with bool _IsMove = true; _BI1 = volatile int*; _BI2 = volatile int*]’
/usr/include/c++/7/bits/stl_algobase.h:598:5:   required from ‘_BI2 std::__copy_move_backward_a2(_BI1, _BI1, _BI2) [with bool _IsMove = true; _BI1 = __gnu_cxx::__normal_iterator<volatile int*, std::vector<volatile int> >; _BI2 = __gnu_cxx::__normal_iterator<volatile int*, std::vector<volatile int> >]’
/usr/include/c++/7/bits/stl_algobase.h:668:48:   required from ‘_BI2 std::move_backward(_BI1, _BI1, _BI2) [with _BI1 = __gnu_cxx::__normal_iterator<volatile int*, std::vector<volatile int> >; _BI2 = __gnu_cxx::__normal_iterator<volatile int*, std::vector<volatile int> >]’
/usr/include/c++/7/bits/stl_algo.h:1851:8:   required from ‘void std::__insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<volatile int*, std::vector<volatile int> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]’
/usr/include/c++/7/bits/stl_algo.h:1885:25:   required from ‘void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<volatile int*, std::vector<volatile int> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]’
/usr/include/c++/7/bits/stl_algo.h:1971:31:   required from ‘void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<volatile int*, std::vector<volatile int> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]’
/usr/include/c++/7/bits/stl_algo.h:4836:18:   required from ‘void std::sort(_RAIter, _RAIter) [with _RAIter = __gnu_cxx::__normal_iterator<volatile int*, std::vector<volatile int> >]’
wtf.cc:10:29:   required from here
/usr/include/c++/7/bits/stl_algobase.h:570:33: error: invalid conversion from ‘volatile void*’ to ‘void*’ [-fpermissive]
      __builtin_memmove(__result - _Num, __first, sizeof(_Tp) * _Num);
                        ~~~~~~~~~^~~~~~
<built-in>: note:   initializing argument 1 of ‘void* __builtin_memmove(void*, const void*, long unsigned int)’
/usr/include/c++/7/bits/stl_algobase.h:570:23: error: invalid conversion from ‘const volatile void*’ to ‘const void*’ [-fpermissive]
      __builtin_memmove(__result - _Num, __first, sizeof(_Tp) * _Num);
      ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<built-in>: note:   initializing argument 2 of ‘void* __builtin_memmove(void*, const void*, long unsigned int)’
/usr/include/c++/7/bits/stl_algobase.h: In instantiation of ‘static _Tp* std::__copy_move<_IsMove, true, std::random_access_iterator_tag>::__copy_m(const _Tp*, const _Tp*, _Tp*) [with _Tp = volatile int; bool _IsMove = true]’:
/usr/include/c++/7/bits/stl_algobase.h:386:44:   required from ‘_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = true; _II = volatile int*; _OI = volatile int*]’
/usr/include/c++/7/bits/stl_algobase.h:422:45:   required from ‘_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = true; _II = volatile int*; _OI = volatile int*]’
/usr/include/c++/7/bits/stl_algobase.h:455:8:   required from ‘_OI std::copy(_II, _II, _OI) [with _II = std::move_iterator<volatile int*>; _OI = volatile int*]’
/usr/include/c++/7/bits/stl_uninitialized.h:101:27:   required from ‘static _ForwardIterator std::__uninitialized_copy<true>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<volatile int*>; _ForwardIterator = volatile int*]’
/usr/include/c++/7/bits/stl_uninitialized.h:134:15:   required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<volatile int*>; _ForwardIterator = volatile int*]’
/usr/include/c++/7/bits/stl_uninitialized.h:289:37:   required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<volatile int*>; _ForwardIterator = volatile int*; _Tp = volatile int]’
/usr/include/c++/7/bits/stl_vector.h:1263:35:   required from ‘std::vector<_Tp, _Alloc>::pointer std::vector<_Tp, _Alloc>::_M_allocate_and_copy(std::vector<_Tp, _Alloc>::size_type, _ForwardIterator, _ForwardIterator) [with _ForwardIterator = std::move_iterator<volatile int*>; _Tp = volatile int; _Alloc = std::allocator<volatile int>; std::vector<_Tp, _Alloc>::pointer = volatile int*; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’
/usr/include/c++/7/bits/vector.tcc:73:40:   required from ‘void std::vector<_Tp, _Alloc>::reserve(std::vector<_Tp, _Alloc>::size_type) [with _Tp = volatile int; _Alloc = std::allocator<volatile int>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’
wtf.cc:8:50:   required from here
/usr/include/c++/7/bits/stl_algobase.h:368:23: error: invalid conversion from ‘volatile void*’ to ‘void*’ [-fpermissive]
      __builtin_memmove(__result, __first, sizeof(_Tp) * _Num);
      ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<built-in>: note:   initializing argument 1 of ‘void* __builtin_memmove(void*, const void*, long unsigned int)’
/usr/include/c++/7/bits/stl_algobase.h:368:23: error: invalid conversion from ‘const volatile void*’ to ‘const void*’ [-fpermissive]
<built-in>: note:   initializing argument 2 of ‘void* __builtin_memmove(void*, const void*, long unsigned int)’

Ошибки компиляции сохраняются, если я удаляю только одну из двух volatiles. Я должен удалить оба, чтобы ошибки прекратились; но, как я сказал выше, я боюсь, что это будет неправильно.

Если и как я могу использовать volatile в приведенном выше фрагменте?

1 Ответ

2 голосов
/ 12 марта 2019

Как использовать энергозависимый вектор?

Вы можете использовать энергозависимый вектор, не вызывая ни одну из его функций-членов.Это не вариант, если вы собираетесь отсортировать вектор.Они не могут быть вызваны, так как ни один из них не является волатильно-квалифицированным.

Вы не можете использовать тип энергозависимого квалифицированного элемента с вектором.

AFAIK, здесь необходимо летучее

Это не единственный способ предотвратить потенциальную оптимизацию.Кроме того, вы можете прочитать отсортированный вектор.(Технически компилятор все еще может заменить сортировку, поскольку результат может быть вычислен во время компиляции. Вероятно, на практике этого не произойдет, и его можно будет более эффективно предотвратить с помощью ввода во время выполнения).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...