代码之家  ›  专栏  ›  技术社区  ›  Collin Dauphinee

通过引用引发非常量临时变量

  •  1
  • Collin Dauphinee  · 技术社区  · 16 年前

    通过非常量引用在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.什么东西包含垃圾,而e.在哪里保持完整?例如:
    E.哪里是“123”
    get()返回大量的垃圾数据,直到它恰好碰到一个空字节。

    1 回复  |  直到 16 年前
        1
  •  6
  •   AnT stands with Russia    16 年前

    没有所谓的“参照投掷”。这是完全不可能的。这是没有语法的。每次尝试“抛出引用”时,实际上都会抛出被引用对象的副本。不用说,在代码中没有通过引用抛出的尝试。

    有可能 抓住 以前通过引用(甚至是非常量)引发的异常,并通过它修改临时异常对象。它会起作用的。实际上,您可以重新抛出现在修改的 现有的 异常对象而不是创建 新的 一个。也就是说,你可以

    throw;
    

    而不是

    throw e;
    

    在catch子句中,仍然可以得到行为正确的代码,即原始对象(经过修改)将通过处理程序层次结构继续运行。

    但是,您的代码在

    e.app("1"); 
    

    呼叫(以及其他呼叫 app )因为参数是非常量引用。改变 应用程序 向任何一方声明

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

    以便编译。

    否则,您的代码应该可以正常工作。你不应该从 get() . 如果你这样做了,那一定是你的编译器出了问题,或者是你没有显示的代码出了问题。

    推荐文章