View mode: basic / threaded / horizontal-split · Log in · Help
July 19, 2012
~= call copy ctor?
I have a 2 questions.

I have this code:

[code]
import std.stdio;

struct Test {
public:
	this(int i = 0) {
		writeln("Test CTor.");
	}

	this(this) {
		writeln("Test Copy CTor");
	}

	~this() {
		writeln("Test DTor");
	}
}

Test[] _arr;

void copy_save(Test t) {
	_arr ~= t;
}

void by_ref_save(ref Test t) {
	_arr ~= t;
}

[/code]

Why get i with

[code]
void main() {
	Test t = 42;

	by_ref_save(t);
}
[/code]

this output:

Test CTor.
Test Copy CTor
Test DTor

?

Why t is copied?

And the same if i have this:

[code]
void main() {
	Test t = 42;

	copy_save(t);
}
[/code]

t is already a clone. Why it is copied again?

Thanks in advance. :)
July 19, 2012
Re: ~= call copy ctor?
On 07/19/2012 02:27 PM, Namespace wrote:
> I have a 2 questions.
> 
> I have this code:
> 
> [code]
> import std.stdio;
> 
> struct Test {
> public:
>     this(int i = 0) {
>         writeln("Test CTor.");
>     }
> 
>     this(this) {
>         writeln("Test Copy CTor");
>     }
> 
>     ~this() {
>         writeln("Test DTor");
>     }
> }
> 
> Test[] _arr;
> 
> void copy_save(Test t) {
>     _arr ~= t;
> }
> 
> void by_ref_save(ref Test t) {
>     _arr ~= t;
> }
> 
> [/code]
> 
> Why get i with
> 
> [code]
> void main() {
>     Test t = 42;
> 
>     by_ref_save(t);
> }
> [/code]
> 
> this output:
> 
> Test CTor.
> Test Copy CTor
> Test DTor

As you mentioned in the subject the copy constructor is not called while
the struct is passed by reference but on array concatenation.
But this must occur since the array has its memory region and the
original variable t in main() also has. Since they are different, at
some point the struct must be copied from t in main() into the array.
The "ref" only ensures that it is passed via reference (a pointer to the
memory of t in main()) to the function by_ref_save().

> And the same if i have this:
> 
> [code]
> void main() {
>     Test t = 42;
> 
>     copy_save(t);
> }
> [/code]
> 
> t is already a clone. Why it is copied again?

Here it is once copied from t in main() into the local variable t in
copy_save() and then copied (as in your 1st example) into the array.
Imagine the copy_save routine is in a different module and only its
signature is exposed to main. When calling the function, the compiler
does not know what happens inside copy_save but it must put the variable
onto the stack at the position of the first parameter (well, in this
case it is probably put into a CPU register, but that doesn't matter here).

Then, when copy_save is invoked it only knows the local variable which
it then copies into the array memory (after enlarging the array).

It *may* be the when you enable compiler optimizations (-O -inline) that
copy_save gets inlined and hence the compiler can optimize one of the
copy calls away. But that I don't know for sure.

Best regards,

Matthias
July 19, 2012
Re: ~= call copy ctor?
Is there any way to avoid the implizit copy ctor by array 
concatenation?
Or is the only way to use a pointer?
July 19, 2012
Re: ~= call copy ctor?
On 07/19/2012 03:00 PM, Namespace wrote:
> Is there any way to avoid the implizit copy ctor by array concatenation?
> Or is the only way to use a pointer?

Yes, in some way you have to. If you want to not copy a lot of data (or
avoid additional on-copy effort) you either have to you pointers
explicitly (Test*[]) or implicitly. The latter works e.g. by making Test
a class which means that the variable actually does store a pointer to
the instance.

Note that for struct pointers you should not escape them, i.e. have a
variable local in a function, puts its address into some array and
returning that array. Since the local variable is gone, the pointer is
invalid as well. (Nothing happens if you do not access it).

Best regards,

Matthias
July 19, 2012
Re: ~= call copy ctor?
Ok, so if a put a struct into an array, it will copied into the 
array. But then? How it is deleted?

For exmaple, i have this code:

[code]
import std.stdio;

struct Test {
public:
	static uint _counter;

	this(int i = 0) {
		writeln("Test CTor.");

		_counter++;
	}

	this(this) {
		writeln("Test Copy CTor");

		_counter++;
	}

	~this() {
		writeln("Test DTor");

		if (_counter > 0) {
			_counter--;
		}
	}
}

void main() {
	{
		Test[] _arr;

		void copy_save(Test t) {
			_arr ~= t;
		}

		void by_ref_save(ref Test t) {
			_arr ~= t;
		}

		Test t = 42;

		//copy_save(t);
		by_ref_save(t);

		writeln("end scope");
	}

	writefln("Counter: %d", Test._counter);
}
[/code]

_counter is still 1 but the scope is released. How is that 
possible?
Even with _arr.clear(); at the end of the scope, _counter is 
still 1.
I see one CTor and one Copy CTor but only one DTor.
July 19, 2012
Re: ~= call copy ctor?
Use std.algorithm.move if you want to avoid the copy ctor call.
July 19, 2012
Re: ~= call copy ctor?
On Thursday, 19 July 2012 at 14:31:02 UTC, Timon Gehr wrote:
> Use std.algorithm.move if you want to avoid the copy ctor call.

With "move" I see the lost DTor call, but not without. Ist that a 
bug? o.O
July 19, 2012
Re: ~= call copy ctor?
On Thursday, 19 July 2012 at 15:36:01 UTC, Namespace wrote:
> _counter is still 1 but the scope is released. How is that 
> possible?
> Even with _arr.clear(); at the end of the scope, _counter is 
> still 1.
> I see one CTor and one Copy CTor but only one DTor.

_arr is actually a dynamic array, which allocates from the 
garbage collector. When _arr goes out of scope, you are only 
destroying the "Slice" that is looking at the data, but not the 
data itself. You have to wait until the Garbage Collector runs 
and collects.

Either that, or use a stack allocated static array, but I 
wouldn't recommend it.

Furthermore, D does not actually guarantee that all your objects 
are destroyed (eg. destructors called) when the program ends. D's 
approach is "The program has ended, ergo anything left in memory 
is moot. Just let the OS clear it."

If you really need RAII, you can use RefCounted objects, such as 
RefCounted! directly, or by using Array.
July 20, 2012
Re: ~= call copy ctor?
New question:

I have this code:
[code]
import std.stdio;

struct Test {
public:
	this(int i = 0) {
		writeln("CTOR");
	}

	this(this) {
		writeln("COPY CTOR");
	}

	~this() {
		writeln("DTOR");
	}
}

void main() {
	Test[] _arr;

	_arr ~= Test(0);

	writeln("end main");
}
[/code]

And as output i see:

CTOR
COPY CTOR
DTOR
end main

Why on earth....?

I create a struct Test. It's not a local variable, it's directly 
assigned,
but it is copied and the original is destroyed. Why?
If i store something important, like a pointer, in Test and will 
free him in the DTOR i cannot assign this way Test's to an array, 
because the pointer was deleted because the DTOr was called.

I think the correct output would be:

CTOR
end main

Maybe DTOR before "end main". But not COPY CTOR anywhere.
July 20, 2012
Re: ~= call copy ctor?
On Fri, 20 Jul 2012 14:50:19 +0100, Namespace <rswhite4@googlemail.com>  
wrote:

> New question:
>
> I have this code:
> [code]
> import std.stdio;
>
> struct Test {
> public:
> 	this(int i = 0) {
> 		writeln("CTOR");
> 	}
>
> 	this(this) {
> 		writeln("COPY CTOR");
> 	}
>
> 	~this() {
> 		writeln("DTOR");
> 	}
> }
>
> void main() {
> 	Test[] _arr;
>
> 	_arr ~= Test(0);
>
> 	writeln("end main");
> }
> [/code]
>
> And as output i see:
>
> CTOR
> COPY CTOR
> DTOR
> end main
>
> Why on earth....?
>
> I create a struct Test. It's not a local variable, it's directly  
> assigned,
> but it is copied and the original is destroyed. Why?

Because that's how assignment works, rhs is evaluated, struct is  
constructed, then assigned to lhs, lhs copies the variable into the  
array.  Your variable is a struct, so it is copied.  Use a pointer instead  
and the pointer is copied into the array.  Use a reference and the  
reference is copied into the array.  The variable, whatever it is, is  
/always/ copied into the array.

It's a long standing optimisation issue and the reason for the recent  
distinction between lvalues and rvalues made in C++0x for their new 'move'  
optimisation where assignments involving rvalues/temporaries can move the  
rvalue instead of copying - or something like that, I'm a bit vague having  
watched a vid a few days back and not paying a lot of attention to it,  
sorry.

Does:

_arr[0] = Test(0);

avoid the copy construction?

R
« First   ‹ Prev
1 2 3 4 5
Top | Discussion index | About this forum | D home