Instead of this ¹non-standard code:
#import <string>
#import <iostream>
void example(const std::string& x) {
  size_t length = x.length();
  for (size_t i = 0; i < length; ++i) {
    std::cout << x.at(i) << std::endl;
  }
}
int main() {
  example("hello");
}
… I'd write this:
#include <string>
#include <iostream>
using namespace std;
void example( string const& s )
{
    for( char const ch : s )
    {
        cout << ch << '\n';
    }
}
auto main()
    -> int
{ example( "hello" ); }
The main place I could add const, relative to the original code, was for the ch variable in the loop. I think that's nice. const is generally desirable because it reduces the possible code actions one has to consider, and range based loops let you have more const.
The main drawback of using const for most things, is when you have to relate to C APIs.
Then one just has to make some gut feeling decisions about whether to copy data, or trust in the documentation and use a const_cast.
        Addendum 1:
Do note that const on a return type prevents move semantics.  As far as I know this was first noted by Andrei Alexandrescu in his Mojo (C++03 move semantics) article in Dr Dobbs Journal:
” [A] const temporary looks like an oxymoron, a contradiction in terms. Seen from a practical perspective, const temporaries force copying at destination.
So, this is one place where one should not use const.
Sorry that I forgot to mention this originally; I was reminded by user bogdan's comment on another answer.
        Addendum 2:
In the same vein (to support move semantics), if the last thing done with a formal argument is to store a copy somewhere, then instead of passing by reference to const it can be better to use a non-const argument passed by value, because it can be simply moved from.
I.e., instead of
string stored_value;
void foo( string const& s )
{
    some_action( s );
    stored_value = s;
}
… or the redundancy of optimized
string stored_value;
void foo( string const& s )
{
    some_action( s );
    stored_value = s;
}
void foo( string&& s )
{
    some_action( s );
    stored_value = move( s );
}
… consider just writing
string stored_value;
void foo( string s )
{
    some_action( s );
    stored_value = move( s );
}
It can be slightly less efficient for the case of lvalue actual argument, it discards the advantages of const (constraints on what the code could possibly do), and it breaks a uniform convention of using const wherever possible, but it doesn't perform badly in any situation (which is the main goal, to avoid that) and it's smaller and possibly more clear code.
Notes:
¹ Standard C++ does not have an #import directive. Also, those headers, when properly included, are not guaranteed to define size_t in the global namespace.