Yang ini tidak menghasilkan kesalahan kompiler, tetapi kesalahan runtime. Alih-alih mengukur waktu yang salah, Anda mendapatkan pengecualian yang mungkin juga dapat diterima.
Setiap konstruktor yang ingin Anda jaga membutuhkan argumen default yang set(guard)dipanggil.
struct Guard {
Guard()
:guardflagp()
{ }
~Guard() {
assert(guardflagp && "Forgot to call guard?");
*guardflagp = 0;
}
void *set(Guard const *&guardflag) {
if(guardflagp) {
*guardflagp = 0;
}
guardflagp = &guardflag;
*guardflagp = this;
}
private:
Guard const **guardflagp;
};
class Foo {
public:
Foo(const char *arg1, Guard &&g = Guard())
:guard()
{ g.set(guard); }
~Foo() {
assert(!guard && "A Foo object cannot be temporary!");
}
private:
mutable Guard const *guard;
};
Ciri-cirinya adalah:
Foo f() {
// OK (no temporary)
Foo f1("hello");
// may throw (may introduce a temporary on behalf of the compiler)
Foo f2 = "hello";
// may throw (introduces a temporary that may be optimized away
Foo f3 = Foo("hello");
// OK (no temporary)
Foo f4{"hello"};
// OK (no temporary)
Foo f = { "hello" };
// always throws
Foo("hello");
// OK (normal copy)
return f;
// may throw (may introduce a temporary on behalf of the compiler)
return "hello";
// OK (initialized temporary lives longer than its initializers)
return { "hello" };
}
int main() {
// OK (it's f that created the temporary in its body)
f();
// OK (normal copy)
Foo g1(f());
// OK (normal copy)
Foo g2 = f();
}
Kasus f2, f3dan kembalinya "hello"mungkin tidak diinginkan. Untuk mencegah pelemparan, Anda dapat mengizinkan sumber salinan menjadi sementara, dengan menyetel ulang guardmenjadi sekarang lindungi kami, bukan sumber salinan. Sekarang Anda juga melihat mengapa kami menggunakan petunjuk di atas - ini memungkinkan kami untuk menjadi fleksibel.
class Foo {
public:
Foo(const char *arg1, Guard &&g = Guard())
:guard()
{ g.set(guard); }
Foo(Foo &&other)
:guard(other.guard)
{
if(guard) {
guard->set(guard);
}
}
Foo(const Foo& other)
:guard(other.guard)
{
if(guard) {
guard->set(guard);
}
}
~Foo() {
assert(!guard && "A Foo object cannot be temporary!");
}
private:
mutable Guard const *guard;
};
Ciri-ciri untuk f2, f3dan untuk return "hello"saat ini selalu // OK.