简体   繁体   English

复制条款的条件?

[英]Conditions for copy elision?

I wanted to verify the if the following optimizations work as expected: 我想验证以下优化是否按预期工作:

  • RVO RVO
  • Named RVO 命名为RVO
  • Copy elision when passing an argument by value 按值传递参数时复制elision

So I wrote this little program: 所以我写了这个小程序:

#include <algorithm>
#include <cstddef>
#include <iostream>
#include <vector>

struct Foo {
    Foo(std::size_t length, char value) : data(length, value) { }

    Foo(const Foo & rhs) : data(rhs.data) { std::cout << "*** COPY ***" << std::endl; }

    Foo & operator= (Foo rhs) {
        std::cout << "*** ASSIGNMENT ***" << std::endl;
        std::swap(data, rhs.data); // probably expensive, ignore this please
        return *this;
    }

    ~Foo() { }

    std::vector<char> data;
};

Foo TestRVO() { return Foo(512, 'r'); }

Foo TestNamedRVO() { Foo result(512, 'n'); return result; }

void PassByValue(Foo inFoo) {}

int main()
{
    std::cout << "\nTest RVO: " << std::endl;
    Foo rvo = TestRVO();

    std::cout << "\nTest named RVO: " << std::endl;
    Foo named_rvo = TestNamedRVO();

    std::cout << "\nTest PassByValue: " << std::endl;
    Foo foo(512, 'a');
    PassByValue(foo);

    std::cout << "\nTest assignment: " << std::endl;
    Foo f(512, 'f');
    Foo g(512, 'g');
    f = g;
}

And I compiled it with optimizations enabled: 我在启用优化的情况下编译了它:

$ g++ -o test -O3 main.cpp ; ./test

This is output: 这是输出:

Test RVO: 

Test named RVO: 

Test PassByValue: 
*** COPY ***

Test assignment: 
*** COPY ***
*** ASSIGNMENT ***

According to the output RVO and named RVO work as expected. 根据输出RVO并命名为RVO按预期工作。 However, copy elision is not performed for the assignment operator and when calling PassByValue . 但是,在调用PassByValue时,不会为赋值运算符执行复制PassByValue

Is copy elision not allowed on user defined copy-constructors? 用户定义的复制构造函数不允许复制省略吗? (I know that RVO is explicitly allowed by the standard but I don't know about copy elision when passing by value.) Is there a way to verify copy elision without defining copy constructors? (我知道标准明确允许RVO,但是当通过值传递时我不知道复制省略。)有没有办法在不定义复制构造函数的情况下验证复制省略?

The standard says (in paragraph 12.8.15): 标准说(第12.8.15段):

This elision of copy operations is permitted in the following circumstances (which may be combined to eliminate multiple copies): 在以下情况下允许复制操作的这种省略(可以组合以消除多个副本):

  • in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object with the same cv-unqualified type as the function return type, the copy operation can be omitted by constructing the automatic object directly into the function's return value 在具有类返回类型的函数的return语句中,当表达式是具有与函数返回类型相同的cv-nonqualified类型的非易失性自动对象的名称时,可以通过构造自动对象来省略复制操作直接进入函数的返回值

  • when a temporary class object that has not been bound to a reference (12.2) would be copied to a class object with the same cv-unqualified type, the copy operation can be omitted by constructing the tempo- rary object directly into the target of the omitted copy 当一个尚未绑定到引用(12.2)的临时类对象被复制到具有相同cv-unqualified类型的类对象时,可以通过将临时对象直接构造到目标中来省略复制操作。省略副本

Neither of these cases applies here, so the elision is not allowed. 这些情况都不适用于此,因此不允许使用省略号。 The first on is obvious (no return). 第一个是显而易见的(没有回报)。 The second is not allowed, because the object you pass in is not a temporary. 第二个是不允许的,因为您传入的对象不是临时的。

Note that your code is still fine, because you would have to create the copy anyway. 请注意,您的代码仍然正常,因为您无论如何都必须创建副本。 To make away with that copy, you would have to use C++0x's move-semantics. 要废除该副本,您必须使用C ++ 0x的移动语义。

The way you use the copy constructor it can not be elided, as the copied object still exists after the call. 您使用复制构造函数的方式无法省略,因为复制的对象在调用后仍然存在。

If you try it this way, it might work better: 如果你这样尝试,它可能会更好:

PassByValue(Foo(512, 'a')); 

All optimizations are allowed but not required, so it is up to each compiler to decide what it can and will do. 所有优化都是允许的,但不是必需的,因此由每个编译器决定它能做什么和将做什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM