Trying for an efficient and readable heap-sort implementation I'm looking for any sort of optimization and/or conventional practice tips, such as using the appropriate data types and naming my variables appropriately.
#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;cstdlib&gt;
#include &lt;ctime&gt;

constexpr short MIN_ELEMS = 3;
constexpr short MAX_ELEMS = 15;
constexpr short LARGEST_ELEM_INT = 99;

void fill_vector(std::vector&lt;int&gt; &amp;v, short MAX_ELEMS, short LARGEST_ELEM_INT);

void print_vector(const std::vector&lt;int&gt;::iterator start, const std::vector&lt;int&gt;::iterator end);

void max_heap(const std::vector&lt;int&gt;::iterator elem, const std::vector&lt;int&gt;::iterator start, std::vector&lt;int&gt;::iterator end);

void heap_sort(const std::vector&lt;int&gt;::iterator start, const std::vector&lt;int&gt;::iterator end);

int main() {
  srand(time(NULL));
  short random_range = rand() % MAX_ELEMS + 1;
  short num_of_elems = random_range &lt; MIN_ELEMS ? MIN_ELEMS : random_range; // prevents num_of_elems from being less than MIN_ELEMS

  std::vector&lt;int&gt; v;
  fill_vector(v, num_of_elems, LARGEST_ELEM_INT);

  print_vector(v.begin(), v.end());

  heap_sort(v.begin(), v.end());

  print_vector(v.begin(), v.end());
}

void fill_vector(std::vector&lt;int&gt; &amp;v, short num_of_elems, short LARGEST_ELEM_INT) {
  short i = 0;
  while (++i, i &lt;= num_of_elems) {
    v.push_back(rand() % LARGEST_ELEM_INT);
  }
}

void print_vector(const std::vector&lt;int&gt;::iterator start, const std::vector&lt;int&gt;::iterator end) {
  for (auto elem = start; elem != end; ++elem) {
    std::cout &lt;&lt; *elem &lt;&lt; ' ';
  }
  std::cout &lt;&lt; '\n';
}

void max_heap(const std::vector&lt;int&gt;::iterator elem, const std::vector&lt;int&gt;::iterator start, const std::vector&lt;int&gt;::iterator end) {
  auto biggest = elem;

  auto left_child = start+((elem-start)*2+1);
  auto right_child = start+((elem-start)*2+2);

  if (left_child &lt; end &amp;&amp; *left_child &gt; *biggest) {
    biggest = left_child;
  }

  if (right_child &lt; end &amp;&amp; *right_child &gt; *biggest) {
    biggest = right_child;
  }

  if (elem != biggest) {
    auto val = *biggest;
    *biggest = *elem;
    *elem = val;
    max_heap(biggest, start, end);
  }
}

void heap_sort(const std::vector&lt;int&gt;::iterator start, const std::vector&lt;int&gt;::iterator end) {
  // sort vector to max heap
  for (auto i = start+((end-start)/2)-1; i &gt;= start; --i) {
    max_heap(i, start, end);
  }

  // sort vector in ascending order
  for (auto i = start; i != end-1; ++i) {
    auto val = *start;
    *start = *(start+(end-i-1));
    *(start+(end-i-1)) = val;

    max_heap(start, start, start+(end-i-1));
  }
}
Sort your includes. That way, you can keep track even if there are more of them.

Writing a test-program is a good idea. Though print the seed-value, and allow overriding from the command-line for reproducibility.
In line with that, add a method to test whether a range is ordered, print that result and use it for the exit-code too.

I would expect a function named print_vector() to, you know, print a vector. Not an iterator-range from a vector. Also, encoding the type of an argument in the function-name hurts usability, especially in generic code.

fill_vector() is a curious interface. I would expect get_random_data() which returns the vector.

Know your operators. ++i, i &lt;= num_of_elems is equivalent to ++i &lt;= num_elements.
Anyway, that should be a for-loop, or you could omit i and just count the argument down to zero.

Kudos for using constexpr to avoid preprocessor-cnstants where not needed. Still, ALL_CAPS_AND_UNDERSCORES identifiers are generally reserved for preprocessor-macros. They warn/assure everyone that preprocessor-rules apply. Fix the naming too.

The C++ headers &lt;cxxx&gt; modelled on the C headers &lt;xxx.h&gt; only guarantee to put their symbols into ::std. Don't assume they are also in the global namespace.

max_heap() will often try to create pointers far beyond the passed range. Creating such a pointer invokes undefined behavior.
For simple and correct code, better use indices.