อันนี้ไม่ส่งผลให้เกิดข้อผิดพลาดของคอมไพเลอร์ แต่เป็นข้อผิดพลาดรันไทม์ แทนที่จะวัดเวลาผิดคุณจะได้รับข้อยกเว้นซึ่งอาจยอมรับได้เช่นกัน
ตัวสร้างใด ๆ ที่คุณต้องการป้องกันจำเป็นต้องมีอาร์กิวเมนต์เริ่มต้นที่set(guard)
ถูกเรียก
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;
};
ลักษณะคือ:
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();
}
กรณีของf2
, f3
และการกลับมาของ"hello"
อาจจะไม่เป็นที่ต้องการ เพื่อป้องกันการขว้างปาคุณสามารถอนุญาตให้แหล่งที่มาของสำเนาเป็นแบบชั่วคราวได้โดยการตั้งค่าใหม่guard
เพื่อป้องกันเราแทนแหล่งที่มาของสำเนา ตอนนี้คุณจะเห็นว่าเหตุใดเราจึงใช้คำแนะนำด้านบนซึ่งช่วยให้เรามีความยืดหยุ่น
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;
};
ลักษณะสำหรับf2
, f3
และตอนนี้เสมอreturn "hello"
// OK