- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
想象一下:
S f(S a) {
return a;
}
为什么不允许别名a
和返回值槽?
S s = f(t);
S s = t; // can't generally transform it to this :(
如果 S
的复制构造函数有副作用,规范不允许这种转换。相反,它至少需要两份拷贝(一份从 t
到 a
,一份从 a
到返回值,另一份从返回s
的值,只有最后一个可以省略。请注意,我在上面写了 = t
来表示 t
拷贝的事实到 f 的 a
,唯一的拷贝在存在移动/复制构造函数的副作用的情况下仍然是强制性的)。
这是为什么呢?
最佳答案
这就是为什么复制省略对参数没有意义。这实际上是关于在编译器级别实现概念的。
复制省略的工作原理是在原地构造返回值。该值不会被复制出来;它是直接在其预期目的地创建的。为预期输出提供空间的是调用者,因此最终是调用者为省略提供了可能性。
为了消除拷贝,函数内部需要做的就是在调用者提供的位置构造输出。如果函数可以做到这一点,你会得到复制省略。如果函数不能,那么它将使用一个或多个临时变量来存储中间结果,然后将其复制/移动到调用者提供的位置。它仍然是就地构造的,但输出的构造是通过复制发生的。
因此,特定函数之外的世界不必知道或关心函数是否进行省略。具体来说,函数的调用者不必知道函数是如何实现的。它没有做任何不同的事情。是函数本身决定是否可以省略。
值参数的存储也由调用者提供。当您调用 f(t)
时,调用者会创建 t
的拷贝并将其传递给 f
。类似地,如果 S
可以从 int
隐式构造,那么 f(5)
将从5 并将其传递给 f
.
这一切都是由调用者完成的。被调用者不知道也不关心它是变量还是临时变量;它只是给了一个堆栈内存(或寄存器或其他任何东西)。
现在请记住:复制省略有效,因为被调用的函数将变量直接构造到输出位置。因此,如果您试图忽略值参数的返回,那么值参数的存储也必须是输出存储本身。但请记住:调用者为参数和输出提供存储。因此,为了省略输出拷贝,调用者必须将参数直接构造到输出中。
为此,现在调用者需要知道它正在调用的函数将忽略返回值,因为如果参数将被返回,它只能将参数直接粘贴到输出中。这在编译器级别通常是不可能的,因为调用者不一定具有函数的实现。如果函数是内联的,那么它也许可以工作。但否则没有。
因此,C++ 委员会并没有考虑到这种可能性。
关于c++ - 为什么按值参数从 NRVO 中排除?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6009278/
我看到了这个问题 When is an object "out of scope"? 我看了sparc_spread 的回答,发现其中有一个问题。在他的回答的这一部分: Circle myFunc (
在程序中如下 #include struct A { A() { std::cout << "0"; } A( const A & ) { std::cout << "1"; }
在以下示例中,根据 this article 应用 NRVO(命名返回值优化): std::string f1() { std::string str; return str; //
#include using namespace std; int gc = 0; struct A { int id; A():id(gc++) { cout 1)。并且符合规范
class Date { private: int day,month,year; public: Date (int d,int m,int y) { day=d; month=m; year=y;
我们有一个广泛使用 out 参数的代码库,因为每个函数都可能因某些错误枚举而失败。这变得非常困惑,代码有时不可读。 我想消除这种模式并引入更现代的方法。 目标是转变: error_t fn(param
当我在 VS2010 中运行此代码时,不应用 NRVO。 #include class A { public: A() { printf( "I am in constructor\
我认为应该这样做,因为它对正确性很重要。但是,我很惊讶地看到 Clang 的输出。考虑以下代码: #include struct S { int i; S(int i) : i(i)
我希望了解 C++ 中 NRVO 的局限性。具有初始命名声明和单个返回的函数是否会针对 NRVO 进行优化并省略 T val,即使函数 myFunc() 具有抛出的可能性? T myFunc(bool
我有以下代码。 #include struct Box { Box() { std::cout << "constructed at " << this << '\n'; }
返回值优化机制的简短(可能过时且过于简单)总结如下 this : an implementation may create a hidden object in the caller's stack
我已经阅读了一些关于 move 函数的帖子(例如 http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c
我需要调用一个函数为我返回一个对象。问题是对象有一个析构函数,它可以在函数输出被分配给另一个对象之前破坏数据。在我的程序中,我有一个 operator+,它将两个矩阵相加并返回两个矩阵的和: C=A+
我刚刚了解了 RVO(返回值优化)和 NRVO(命名返回值优化)。下面是两个例子 //Example of RVO Bar Foo() { return Bar(); } //Example
如果我编写一个在本地实例化对象然后按值返回的工厂方法,打算利用 NRVO(根据此处的一些答案:c++11 Return value optimization or move?),将指向本地对象的指针/
假设我有这样一个函数: using std::vector; vector build_vector(int n) { if (some_condition(n)) return {};
假设我们有以下代码: std::vector f() { std::vector y; ... return y; } std::vector x = ... x = f(); 似乎编译器
想象一下: S f(S a) { return a; } 为什么不允许别名a和返回值槽? S s = f(t); S s = t; // can't generally transform it
我一直在研究 NRVO 及其对不同编译器的支持,并遇到了奇怪的行为,这相当令人困惑。 示例代码: #include using namespace std; class X
自 1992 年以来我一直在使用 C++(并阅读了大量有关该语言的资料),因此我对这门语言有相当多的了解,但远非全部。我的问题是关于 C++11 命名返回值优化——有什么保证会执行?我倾向于发送非常量
我是一名优秀的程序员,十分优秀!