I've not tried to use the conflict refiner API. Probably should look into it... but I use the conflict refiner a lot in the standalone interactive CPLEX. I am not aware of any issues of keeping copies of the constraints in your own code - I have done it before in CPLEX & Concert with C++. It may be a conceptual misunderstanding of what the conflict refiner does...
Remember that it is very rare to have a single identifiable infeasible constraint. It is much more common that there is a set of constraints that cannot be satisfied together, but if any of that set of constraints is removed then the rest are then feasible. This is usually called the "irreducible infeasible set".
Think for example of three constraints:
a >= b + 1
b >= c + 1
c >= a + 1
Clearly these three constraints cannot be satisfied simultaneously, but take any one away and the other two are then OK. It can be very hard to decide which constraint is wrong in some cases, and really depends on a deeper understanding of the problem and its model.
Anyway, try exporting the model as an LP, MPS or SAV format file and read it into the standalone CPLEX optimiser. Then optimise it - it should also fail with a reported infeasibility. Then run the conflict refiner and then display the computed (irreducible) infeasible set:
read fred.lp
optimize
conflict
display conflict all
I find that MPS files are better at preserving the full precision of the problem and are probably more portable to try with other solvers, but LP files are much more human-readable. The SAV file format is supposed to be the most accurate copy of what CPLEX has in memory, but is very opaque and rather CPLEX-specific. If your problem is clearly infeasible the LP format is probably nicer to work with, but if the problem is borderline infeasible you may get different behaviour from the LP file. It would probably help you a great deal if you name all your variables ad constraints too. Maybe just do the naming in debug builds or add a flag to control whether or not to do the additional naming.