Topic: Should additional optimization be allowed in regards to overload of value semantics?
Author: Mathias Gaunard <loufoque@gmail.com>
Date: Fri, 10 Aug 2007 14:44:28 CST Raw View
Currently the C++ standard allows an implementation to elide copies,
even if those have side effects, in a number of cases. This is
justified by the fact that we can consider copy constructors to create
real copies of objects with are values.
Additional optimizations in regards to overloading of value semantics
could be interesting to consider allowing.
Let's take this example, which isn't very realistic but shows
optimizations opportunities. (we will assume here that std::string
uses Small String Optimization and that it is expensive to move --
indeed move semantics do not solve the problem)
std::string getline()
{
std::string str;
/* acquire line from stdin */
return str;
}
Let's start with
std::string a = getline();
Here, the C++ standard says that normally a copy should occur, but
that implementations can elide it. This optimization is called NRVO
(Named Return Value Optimization).
However, this isn't much different, and the standard doesn't allow to
optimize this case to be the same as the previous one:
std::string a;
a = getline();
Maybe we could consider that it is useless to default-construct the
value if we only assign it a new value after that, and thus make it
equivalent to the previous code. Of course, this is already done with
PODs.
Then, more interesting, is this case:
std::string a = getline();
a = getline();
With current compilers (that do NRVO), a temporary will be created in
getline() on the second call, then the contents would be copied/moved
to a.
However here, technically, if getline() didn't throw (it probably
throws in that case, but let's say it doesn't for the sake of it), we
could destruct a, then re-construct it in getline() as a new variable
like with NRVO.
So, to sum this up, there are two optimization opportunities that I
would like to discuss to know whether it might be a good idea to
allow them :
- default constructors + assignment --> appropriate (eventually copy)
constructor
- if initialization code does not throw, creation of a temporary +
assignment to variable --> destruction + in-place construction
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Mathias Gaunard <loufoque@gmail.com>
Date: Fri, 10 Aug 2007 18:31:11 CST Raw View
Currently the C++ standard allows an implementation to elide copies,
even if those have side effects, in a number of cases. This is
justified by the fact that we can consider copy constructors to create
real copies of objects with are values.
Additional optimizations in regards to overloading of value semantics
could be interesting to consider allowing.
Let's take this example, which isn't very realistic but shows
optimizations opportunities. (we will assume here that std::string
uses Small String Optimization and that it is expensive to move --
indeed move semantics do not solve the problem)
std::string getline()
{
std::string str;
/* acquire line from stdin */
return str;
}
Let's start with
std::string a = getline();
Here, the C++ standard says that normally a copy should occur, but
that implementations can elide it. This optimization is called NRVO
(Named Return Value Optimization).
However, this isn't much different, and the standard doesn't allow to
optimize this case to be the same as the previous one:
std::string a;
a = getline();
Maybe we could consider that it is useless to default-construct the
value if we only assign it a new value after that, and thus make it
equivalent to the previous code. Of course, this is already done with
PODs.
Then, more interesting, is this case:
std::string a = getline();
a = getline();
With current compilers (that do NRVO), a temporary will be created in
getline() on the second call, then the contents would be copied/moved
to a.
However here, technically, if getline() didn't throw (it probably
throws in that case, but let's say it doesn't for the sake of it), we
could destruct a, then re-construct it in getline() as a new variable
like with NRVO.
So, to sum this up, there are two optimization opportunities that I
would like to discuss to know whether it might be a good idea to
allow them :
- default constructors + assignment --> appropriate (eventually copy)
constructor
- if initialization code does not throw, creation of a temporary +
assignment to variable --> destruction + in-place construction
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: ark@acm.org ("Andrew Koenig")
Date: Sun, 12 Aug 2007 01:44:27 GMT Raw View
"Mathias Gaunard" <loufoque@gmail.com> wrote in message
news:1186774263.114180.36240@i13g2000prf.googlegroups.com...
> constructor
> - if initialization code does not throw, creation of a temporary +
> assignment to variable --> destruction + in-place construction
Destruction might have side effects that change the meaning of the
construction.
For example:
T t;
T* p = &t;
// Do something that gives a value to t, and then...
t = *p;
Now, p might still be equal to &t or it might not. Therefore, it is not
possible for the compiler to determine statically whether this statement is
a self-assignment.
What you are proposing is that the compiler should be permitted to rewrite
this statement as
t.~T(); new(t) T(*p);
and the trouble is that if p == &T, then the "new" will fail because it is
trying to copy an object that has been destroyed.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]