First, you must make your operators accessible:
class Test {
private: 
    int arr[100];
public:
    int operator[](int i) {
        return arr[i];
    }    
    int& operator[](int i) {
        return arr[i];
    }
};
Now, this won't compile (since arr is private):
Test a;
a.arr[5] = 10;
int operator[](int i) returns by value (an rvalue), making a[5] = 10; impossible.  
int& operator[](int i) returns a reference to the int stored in arr (an lvalue) which makes a[5] = 10; possible.
But it won't compile since your operators only differ on the return types (int vs. int&). 
Making the one returning by value const solves that issue:
#include <iostream>
class Test {
private:
    int arr[100];
public:
    int operator[](size_t i) const { // note the const
        std::cout << "using operator[]() const\n";
        return arr[i];
    }
    int& operator[](size_t i) {
        std::cout << "using operator[]() mutable\n";
        return arr[i];
    }
};
void test_const(const Test& t) {
    std::cout << t[5] << "\n";
}
int main() {
    Test a;
    a[5] = 10;
    std::cout << a[5] << "\n";
    test_const(a);
}
Output:
using operator[]() mutable
using operator[]() mutable
10
using operator[]() const
10