C++ 我必须依赖编译器NRVO吗?

C++ 我必须依赖编译器NRVO吗?,c++,optimization,compiler-optimization,C++,Optimization,Compiler Optimization,我需要调用一个函数为我返回一个对象。问题是对象有一个析构函数,它可以在函数输出被分配到另一个对象之前破坏数据。 在我的程序中,我有一个运算符+,它将两个矩阵相加并返回两个矩阵的和: C=A+B 根据名称返回值优化(NRVO),以下代码不应立即调用析构函数: Matrix operator+(const Matrix &m1, const Matrix &m2) { Matrix sum; m1.clone(sum); for... for

我需要调用一个函数为我返回一个对象。问题是对象有一个析构函数,它可以在函数输出被分配到另一个对象之前破坏数据。 在我的程序中,我有一个运算符+,它将两个矩阵相加并返回两个矩阵的和:

C=A+B
根据名称返回值优化(NRVO),以下代码不应立即调用析构函数:

Matrix operator+(const Matrix &m1, const Matrix &m2)
{
    Matrix sum;
    m1.clone(sum);
    for...
        for...
            sum.members[i][j]+=m2.members[i][j];
    return sum;
}
我的问题是,我不相信NRVO,因为它取决于编译器。如果我把代码交给其他人,他可能会编译代码,而他的编译器会给出不同的结果

那么,有没有办法强迫编译器给出我所需要的东西,或者我必须将代码更改为不需要的形式,如下所示

Matrix sum(Matrix &result, const Matrix &m1, const Matrix &m2)
编辑:

为了进一步解释,我假设通过考虑NRVO,问题如下:

compiler reaches to C=A+B
operator + is called
object sum is created
object sum is calculated as sum of m1 and m2
sum is returned but its destructor is not called
the value of sum is directed to variable C
after function containing variable C reaches end, the destructor of C is called.
当未应用NRVO时,我预计:

compiler reaches to C=A+B
operator + is called
object sum is created
object sum is calculated as sum of m1 and m2
sum is returned and its destructor is called which releases all data allocations
the return value of the operator+ is already destroyed so an invalid data is associated to variable C
...
问题是对象有一个析构函数,它可以在函数输出被分配到另一个对象之前破坏数据

这不是问题。对象将被正确复制,或者通过优化消除不必要的复制。如果正确实现了复制ctor,最终结果将是相同的(当然,除了不太理想的代码)。如果对象复制成本过高,您可能应该使用写时复制语义,而实际的矩阵对象将是在堆上创建的真实对象的薄包装

未应用NRVO时实际会发生什么情况:

compiler reaches to C=A+B
operator + is called
object sum is created
object sum is calculated as sum of m1 and m2
temporary object of type Matrix created as a copy of object sum
object sum destroyed
temporary assigned to C
正如您所看到的,最终结果是相同的,只是效率较低(创建了临时对象)

问题是对象有一个析构函数,它可以在函数输出被分配到另一个对象之前破坏数据

这不是问题。对象将被正确复制,或者通过优化消除不必要的复制。如果正确实现了复制ctor,最终结果将是相同的(当然,除了不太理想的代码)。如果对象复制成本过高,您可能应该使用写时复制语义,而实际的矩阵对象将是在堆上创建的真实对象的薄包装

未应用NRVO时实际会发生什么情况:

compiler reaches to C=A+B
operator + is called
object sum is created
object sum is calculated as sum of m1 and m2
temporary object of type Matrix created as a copy of object sum
object sum destroyed
temporary assigned to C
正如您所看到的,最终结果是相同的,只是效率较低(创建了临时对象)

问题是对象有一个析构函数,它可以在函数输出被分配到另一个对象之前破坏数据

这不是问题。对象将被正确复制,或者通过优化消除不必要的复制。如果正确实现了复制ctor,最终结果将是相同的(当然,除了不太理想的代码)。如果对象复制成本过高,您可能应该使用写时复制语义,而实际的矩阵对象将是在堆上创建的真实对象的薄包装

未应用NRVO时实际会发生什么情况:

compiler reaches to C=A+B
operator + is called
object sum is created
object sum is calculated as sum of m1 and m2
temporary object of type Matrix created as a copy of object sum
object sum destroyed
temporary assigned to C
正如您所看到的,最终结果是相同的,只是效率较低(创建了临时对象)

问题是对象有一个析构函数,它可以在函数输出被分配到另一个对象之前破坏数据

这不是问题。对象将被正确复制,或者通过优化消除不必要的复制。如果正确实现了复制ctor,最终结果将是相同的(当然,除了不太理想的代码)。如果对象复制成本过高,您可能应该使用写时复制语义,而实际的矩阵对象将是在堆上创建的真实对象的薄包装

未应用NRVO时实际会发生什么情况:

compiler reaches to C=A+B
operator + is called
object sum is created
object sum is calculated as sum of m1 and m2
temporary object of type Matrix created as a copy of object sum
object sum destroyed
temporary assigned to C


正如您所看到的,最终结果是相同的,只是效率较低(创建了临时对象)

如果您的类按照您所说的做,您需要修复它。您编写的代码不应该依赖于特定的编译器优化来正常工作。听起来您需要阅读有关对象生存期的内容。请指出代码中需要析构函数调用的位置,我们应该能够解决这个问题。@RobertHarvey这正是我的问题。无论如何,要在不失去OO运算符优势的情况下修复它?您认为哪些对象或对象可能会被过早收集?如果您的类按照您所说的做,您需要修复它。您编写的代码不应该依赖于特定的编译器优化来正常运行。听起来您需要阅读有关对象生存期的内容。请指出代码中需要析构函数调用的位置,我们应该能够解决这个问题。@RobertHarvey这正是我的问题。无论如何,要在不失去OO运算符优势的情况下修复它?您认为哪些对象或对象可能会被过早收集?如果您的类按照您所说的做,您需要修复它。您编写的代码不应该依赖于特定的编译器优化来正常运行。听起来您需要阅读有关对象生存期的内容。请指出代码中需要析构函数调用的位置,我们应该能够解决这个问题。@RobertHarvey这正是我的问题。无论如何,要在不失去OO运算符优势的情况下修复它?您认为哪些对象或对象可能会被过早收集?如果您的类按照您所说的做,您需要修复它。您编写的代码不应该依赖于特定的编译器优化来正常运行。听起来您需要阅读有关对象生存期的内容。请指出代码中需要析构函数调用的位置,我们应该能够解决这个问题。@RobertHarvey这正是我的问题。无论如何,在不失去OO操作符优势的情况下修复它?您认为哪些对象或对象可能会被过早收集?