Điều này không dẫn đến lỗi trình biên dịch mà là lỗi thời gian chạy. Thay vì đo sai thời gian, bạn nhận được một ngoại lệ có thể chấp nhận được.
Bất kỳ hàm tạo nào bạn muốn bảo vệ đều cần một đối số mặc định set(guard)được gọi.
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;
};
Các đặc điểm là:
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();
}
Trường hợp của f2, f3và việc trả lại "hello"có thể không được mong muốn. Để tránh bị ném, bạn có thể cho phép nguồn của một bản sao chỉ là nguồn tạm thời, bằng cách đặt lại nguồn guardđể bảo vệ chúng tôi ngay bây giờ thay vì nguồn của bản sao. Bây giờ bạn cũng thấy lý do tại sao chúng tôi sử dụng các con trỏ ở trên - nó cho phép chúng tôi linh hoạt.
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;
};
Các đặc tính cho f2, f3và cho return "hello"bây giờ luôn // OK.