The problem with auto_ptr is that it can be copied and making a copy modifies the original:
a = b;   // transfers ownership from b to a
This is similar to what moving does now, just that at the time of auto_ptr there was no move semantics in the language. Now that C++ has move semantics transfer of ownership can be expressed more clearly:
a = std::move(b);
Nobody would/should expect that b is not modified in that line.
However, with a = b it is commonly assumed, that b is not modified. auto_ptr breaks that assumption. Consider for example:
template <typename P>
void foo() {
    std::vector<P> x;
    x.resize(42);
    int i=0;
    for (auto& e : x) e.reset(new int(i++));
    
    for (auto e : x) {
        std::cout << *e << "\n";        
    }
    for (auto e : x) {
        std::cout << *e << "\n";        
    }    
}
With P=std::unique_ptr<int> this will cause a compiler error:
<source>:17:15: error: call to deleted constructor of 'std::unique_ptr<int, std::default_delete<int> >'
    for (auto e : x) {
              ^ ~
While it compiles with P=std::auto_ptr<int> but is undefined behavior (eg segfault here: https://godbolt.org/z/93hdse), because it dereferences null pointers.
Similar issue with any algorithm assumes it is "ok" to copy elements. For example a comparator for auto_ptr that takes parameters by value does compile but causes havoc:
auto compare = [](auto a,auto b) { return *a < *b; }
std::sort(x.begin(), x.end(),compare);   // BOOM !
Not always is it so obvious that a copy is being made, algorithms may copy elements internally when elements are copyable.