Depending on the definition of
StringSeq it could be fine to silence or ignore the warning here. If you control the
StringSeq you could also add a copy-assignment operator as suggested.
The warning is an observation that a user-provided copy constructor is likely to be inconsistent with an implicitly-declared ("compiler-provided") copy assignment operator. Inconsistency means that the copy-constructor probably makes a "deep copy", where the copy-assignment operator merely makes a "shallow copy".
This is the "Rule of Three", a particularly useful guideline which says "If a class requires a user-defined copy-assignment operator, copy constructor, or destructor, it is likely to require all of them".
https://en.cppreference.com/w/cpp/language/rule_of_three
my_class declared below exhibits the inconsistency that the compiler is warning you about:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
#include <iostream>
class my_class
{
int* px;
public:
my_class(my_class const& that)
: px{ new int{*that.px} }
{}
// should also provide a copy-assignment operator as follows:
// the absence of the following line is the cause of the warning:
// my_class& operator=(my_class const& rhs) { *px = *rhs.px; return *this; }
// the compiler-provided version of this function has different semantics,
// it would perform member-wise assignment as-in the following implementation
// my_class& operator=(my_class const& rhs) { px = rhs.px; return *this; }
// for completeness's sake a destructor should be provided to ensure that
// the memory obtained with new is subsequently and predictably deleted in
// every circumstance:
~my_class() { delete px; }
public:
explicit my_class(int n = 0) : px{ new int{n} } {}
int get() const { return *px; }
void set(int n) { *px = n; }
};
int main()
{
my_class a { 1 };
my_class b { a };
my_class c;
c = a;
std::cout << a.get() << ' ' << b.get() << ' ' << c.get() << '\n'; // 1 1 1
b.set(2); // modifications to b are indepedndent of both a and c
std::cout << a.get() << ' ' << b.get() << ' ' << c.get() << '\n'; // 1 2 1
a.set(3); // modifications to a are reflected in both a and c
std::cout << a.get() << ' ' << b.get() << ' ' << c.get() << '\n'; // 3 2 3
}
|
Ordinarily we would expect the last line of code to print
3 2 1, because after
c = a object
c would conventionally be independent from
a.
The program isn't wrong but just "surprising".
How can I not "copy" the object but replace the one the local result variable points to? |
To decide how to proceed we would need to fully understand
result = var->applyTo(result, offset) so we could adjust its meaning if necessary. In particular we could evaluate adding a
move constructor and
move assignment operator to
StringSeq.
There might be little to change within the code you posted.