LOL, muse1987, that's great.
I have no idea, honestly.
Though I suspect the use of template specialisation, I can't think of any way to do it without declaring over 65000 specialised classes. :sick:
Printable View
LOL, muse1987, that's great.
I have no idea, honestly.
Though I suspect the use of template specialisation, I can't think of any way to do it without declaring over 65000 specialised classes. :sick:
I am afraid I forgot the axiom:Quote:
Originally Posted by Hermit
:o :o :oQuote:
Make things as simple as possible, but no simpler
Rather than code, let me just use words....
A conventional (full) implementation would do a deep copy for post the "temp" and within the "swap". For many cases this is not an issue.
The approach can be optimized so that the number of deep copies is reduced to one (leaving the "swap" to be just a shallow copy [the example code implemented the reverse :blush: ]
However, when there is significant overhead to making a deep copy, assignments (regardless of implementation) become expensive regardless of implementation. At best this type of optimization can only provide a <50% improvement (half the time). Refactoring can eliminate the expense entirely (or at least defer it by techniques such as COW).
If the assignment (and/or copy construction) is going to be so expensive that it will impact application performance, then it is usually a good idea to prevent these from being implicitly invoked in any case.
The choice to "munge" the copy constuctor (vs. a specialized constructor) is another issue. If the practice of using initializer lists for all (possible) construction activities is followed, you end up with code duplication at every constructor. This will cause an increase in maintenance costs and lower reliability. But I agree that it is not an "ideal" solution.
Maybe some form of template meta-programming?Quote:
Originally Posted by Zaccheus
That would work, but is probably too obtuse for any real use.Quote:
Originally Posted by PABLO_ALCH
The testing benefit you mention is not real. If you modify a file in any way, you MUST do a 100% retest of the code that is contained in that file. (You would be willing to risk $1,000,000 that you never had a case of "happy fingers" and made a completely unintentional edit at some other point in the file?).
My concern was not having to make two deep copies. That would be simply ridiculous. swap() can almost always be implemented to simply swap the internal representations without doing any actual work.Quote:
Originally Posted by TheCPUWizard
My concern was the extra memory allocation/deallocation that your method would require. I'm not even talking about particularly large objects. On the contrary, the scenario where this inefficiency would be most pronounced would be the assignment of a large number of small objects. For each assignment, when the temporary object is constructed, a new block of memory will be allocated, and when the temporary object is destructed, the old block of memory that the LHS object used to have (that was swapped into the temporary object) will be freed.
If, as I said, we have a large number of assignments, we have a large number of allocations that would, in a "plain", copy-the-data, implementation, be unnecessary. Given that allocating a block of memory can take significantly longer than copying a small amount of data, this makes the method very inefficient.
Agreed. But sometimes you need to be explicitly making copies of objects. In this case, and especially if you have a large number of objects, it pays off for the assignment operation to be as efficient as possible.Quote:
If the assignment (and/or copy construction) is going to be so expensive that it will impact application performance, then it is usually a good idea to prevent these from being implicitly invoked in any case.
I'm not sure I understand what you mean here... what do you mean by "munging" the copy constructor?Quote:
The choice to "munge" the copy constuctor (vs. a specialized constructor) is another issue. If the practice of using initializer lists for all (possible) construction activities is followed, you end up with code duplication at every constructor. This will cause an increase in maintenance costs and lower reliability. But I agree that it is not an "ideal" solution.
I've only given this a minute of thought, so it's likely broken (not tested):Quote:
Originally Posted by muse1987
What's your solution?Code:enum{TYPE_UCHAR, TYPE_USHRT, TYPE_ULONG};
template<int> struct XTypeResolver;
template<> struct XTypeResolver<TYPE_UCHAR> {typedef unsigned char value_type;};
template<> struct XTypeResolver<TYPE_USHRT> {typedef unsigned short value_type;};
template<> struct XTypeResolver<TYPE_ULONG> {typedef unsigned long value_type;};
template<unsigned long N> class Foo
{
enum
{
VALUE_TYPE_INDEX = (N >= 0 && N < 256) ? TYPE_UCHAR :
(N >= 256 && N < 65536) ? TYPE_USHRT : TYPE_ULONG
};
//Expose this to the user
public: typedef typename XTypeResolver<VALUE_TYPE_INDEX>::value_type value_type;
};
I am sure you are aware (but for the other readers), an object which has MANY member objects (not pointers or references) is allocated in one block. so your point may not apply to many instances.Quote:
Originally Posted by HighCommander4
Also local variable allocation typically takes place upon unter to a method, so if there is ANY allocation it is usually done for the maxiumum amount of local memory needed.
Therefore (if not optimized by ther compiler), the following two samples require the exact same amount of allocation overhead.
Code:void f()
{
int i;
}
[/quote]Code:class X
{
}
class Y
{
X data[1000]
}
void f()
{
X biggie[1000];
}
Both examples will "increment" the stack pointer ONCE and decrement it ONCE upon entry/exit. Hardly an "Expensive" operation.
Again, if you are going to be copying a large object (into an EXISTING instance!) you really have to look at the design.Quote:
Agreed. But sometimes you need to be explicitly making copies of objects. In this case, and especially if you have a large number of objects, it pays off for the assignment operation to be as efficient as possible.
Using an external condition to influence how the copy constructor behaves.Quote:
Not sure I understand what you mean here... what do you mean by "munging" the copy constructor?
In conclusion (at least for this reply), nobody would accept a database which did not adhere to ACID, yet so many people readily accept this in a program without even thinking about the conseuqences.
When you implement an architecture that 100% guarentees that the state of the entire system will be consistant across every statement boundary (ie the statement will have completed sucessfully, or had no visible impact) the number of test cases required is drastically reduced.
Consider the following (bad code) example:
There are now at least 999 additional test cases required since the result of calling f(...) has 1002 possible execution paths rather than exactly two.Code:class X
{
X(int v) {}
X(X const & src)
{
if (m_V == something) {throw....}
}
}
class Y
{
X data[1000];
}
void f(X &x2)
{
X x1;
// code
x2 = x1;
}
I'm sorry if I wasn't clear enough. I was speaking of an object that handles a piece of dynamic (heap) memory, such as your m_Bulk example.Quote:
Originally Posted by TheCPUWizard
In a case like that, the constructor of the temporary would allocate a piece of heap memory for the temporary, swap() would simply swap the m_Bulk pointers of the temporary and the LHS object, and the destructor of the temporary would now deallocate the original piece of memory that the LHS object used to hold.
In a conventional implementation (i.e. straight copying, no copy constructor call/temporaries), assuming that the size of the memory block handled by the RHS object does not exceed that handled by the LHS object, no allocation/reallocation would be necesary. Hence the significant overhead, as allocating/deallocating a piece of heap memory can take significantly longer than copying a small chunk of data.
Point taken. Looking back at the examples in my own code that I was thinking of, it was in fact copy construction that was taking place, and not assignment.Quote:
Again, if you are going to be copying a large object (into an EXISTING instance!) you really have to look at the design.
Exactly.Quote:
Originally Posted by Plasmator
Very nice indeed!Quote:
Originally Posted by muse1987