Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
599 views
in Technique[技术] by (71.8m points)

c++ - Copy elision for pass-by-value arguments

Given

struct Range{
    Range(double from, double to) : from(from), to(to) {}
    double from;
    double to;
};

struct Box{
    Box(Range x, Range y) : x(x), y(y) {}
    Range x;
    Range y;
};

suppose we run Box box(Range(0.0,1.0),Range(0.0,2.0)).

Could a modern compiler with optimizations enabled avoid copying Range objects altogether during this construction? (i.e. construct the Range objects inside box to begin with?)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There are actually two copies being performed on each Range object passed to the constructor. The first happens when copying the temporary Range object into the function parameter. This can be elided as per the reference given in 101010's answer. There are specific circumstances in which copy elision can be performed.

The second copy happens when copying the function parameter into the member (as specified in the constructor initialization list). This cannot be elided, and this is why you still see a single copy being made for each parameter in YSC's answer.

When the copy constructor has side-effects (such as the prints in YSC's answer), copy elision can still be performed for the first copy, but the second copy must remain.

However, the compiler is always free to make changes if they do not alter the observed behavior of the program (this is known as the "as-if" rule). This means that if the copy constructor has no side effects and removing the constructor call will not change the result, the compiler is free to remove even the second copy.

You can see this by analyzing the generated assembly. In this example, the compiler optimizes out not only the copies, but even the construction of the Box object itself:

Box box(Range(a,b),Range(c,d));
std::cout << box.x.from;

Generates identical assembly as:

std::cout << a;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...