通过引用抛出非常量临时值

发布于 2024-08-21 07:49:50 字数 760 浏览 2 评论 0原文

通过非常量引用在 try 块中抛出在堆栈上构造的对象,捕获它并修改它,然后通过引用另一个 catch 块将其抛出,是否有任何问题?

下面是我所指内容的一个简短示例。

struct EC {
    EC(string msg) { what = msg; }
    string where;
    string what;

    void app(string& t) { where += t; }
    string get() { return what; }
};

try {
    try {
        try {
            EC error("Test");
            throw error;
        }
        catch (EC& e) {
            e.app("1");
            throw e;
        }
    }
    catch (EC& e) {
        e.app("2");
        throw e;
    }
}
catch (EC& e) {
     e.app("3");
     cout << e.where << endl;
     cout << e.get() << endl;
}

这是否有可能导致 e.what 包含垃圾,但 e.where 保持完整?例如:
e.“123”在哪里
e.get() 返回大量垃圾数据,直到它碰巧遇到空字节。

Is there any problem with throwing an object constructed on the stack in a try-block by non-const reference, catching it and modifying it, then throwing it by reference to another catch block?

Below is a short example of what I'm refering to.

struct EC {
    EC(string msg) { what = msg; }
    string where;
    string what;

    void app(string& t) { where += t; }
    string get() { return what; }
};

try {
    try {
        try {
            EC error("Test");
            throw error;
        }
        catch (EC& e) {
            e.app("1");
            throw e;
        }
    }
    catch (EC& e) {
        e.app("2");
        throw e;
    }
}
catch (EC& e) {
     e.app("3");
     cout << e.where << endl;
     cout << e.get() << endl;
}

Is it possible that this could cause e.what to contain junk, but e.where to remain intact? For example:

e.where is "123"

e.get() returns a lot of garbage data, until it happens to hit a null byte.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

那些过往 2024-08-28 07:49:50

不存在“通过引用抛出”这样的事情。这根本不可能。没有相应的语法。每次尝试“抛出引用”时,实际上都会抛出引用对象的副本。不用说,您的代码中没有尝试通过引用抛出异常。

可以通过引用(甚至是非常量异常)捕获先前抛出的异常,并通过它修改临时异常对象。它会起作用的。事实上,您可以重新抛出现在已修改的现有异常对象,而不是创建异常对象。即,您可以在 catch 子句中执行

throw;

而不是

throw e;

仍然获得正确行为的代码,即原始对象(经过修改)将继续在处理程序层次结构中飞行。

因此您的代码在调用

e.app("1"); 

但是,由于参数是非常量引用, (以及对 app 的其他调用)时格式不正确。将 app 声明更改为任一

void app(const string& t) { where += t; }  // <- either this
void app(string t) { where += t; }         // <- or this

以便编译。

否则,您的代码应该可以正常工作。您不应该从 get() 获得任何垃圾。如果这样做,则一定是您的编译器有问题,或者是您未显示的代码有问题。

There's no such thing as "throwing by reference". It is simply impossible. There's no syntax for that. Every time you try to "throw a reference", a copy of the referenced object is actually thrown. Needless to say, there are no attempts to throw by reference in your code.

It is possible to catch a previously thrown exception by reference (even by a non-const one) and modify the temporary exception object through it. It will work. In fact, you can re-throw the now-modified existing exception object instead of creating a new one. I.e. you can just do

throw;

instead of

throw e;

in your catch clauses and still get the correctly behaving code, i.e. the original object (with modifications) will continue its flight throgh the handler hierarchy.

However, your code is ill-formed at the

e.app("1"); 

call (and other calls to app) since the parameter is non-const reference. Change the app declaration to either

void app(const string& t) { where += t; }  // <- either this
void app(string t) { where += t; }         // <- or this

for it to compile.

Otherwise, you code should work fine. You are not supposed to get any garbage from get(). If you do, it must be either a problem with your compiler or with your code that you don't show.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文