Alexei wrote:
Now, does it matter if the object is created with gcnew or by calling a
function? No, IMO. The same code I can rewrite with using fi.OpenRead():
{
FileStream ^ fs = fi.OpenRead();
try {
} finally {
delete fs;
}
}
Something like this would be nice, but it can't be done the way you're
trying to do it.
What leads me to simply:
FileStream fs(fi.OpenRead());
I think the code above would expand to
FileStream^ fs = gcnew FileStream(fi.OpenRead());
[...]
and there is no such copy constructor in FileStream (and even if there
was one, you wouldn't want to make a copy in this case).
I can't understand the point of having copy-constructors for ref classes.
There is such a thing as copy c'tor and assignment operator in C++/CLI.
Because what if you want to make a copy? You could always define a
static member (class method) name CopyMe, but C++/CLI was designed to be
as conforming with C++ as possible. The stack syntax with ref classes
has to work like stack objects in native C++, otherwise you're inventing
a new language that has nothing to do with C++. Exactly that happened
with the old MC++, where the destructor syntax was used for the
finalizer. Such a radical change has disadvantages, because C++
programmers have certain expectations about the language, such as the
copy c'tor syntax, even if it's implemented in the underlying .NET layer
differently.
What you're asking for is
cli::auto_ptr<FileStream> fs(fi.OpenRead());
which may or may not exist. If it doesn't, you can try to write your
own. It would have a little bit of an overhead, but only a couple of
extra CLI instructions.
Here's an auto pointer template that I wrote, although it has a
completely different purpose (to store unmanaged objects inside a
managed wrapper):
#pragma once
template <class T>
public ref class CliScopedPtr
{
typedef CliScopedPtr<T> this_type;
public:
CliScopedPtr()
: ptr(nullptr)
{
}
explicit CliScopedPtr(T* p)
: ptr(p)
{
}
~CliScopedPtr()
{
delete ptr;
}
T* get()
{
return ptr;
}
T& operator*()
{
return *ptr;
}
T* operator->()
{
return ptr;
}
bool assigned()
{
return ptr != nullptr;
}
void swap(CliScopedPtr% other)
{
T* tmp = other.ptr;
other.ptr = ptr;
ptr = tmp;
}
void swap(CliScopedPtr^ other)
{
T* tmp = other->ptr;
other->ptr = ptr;
ptr = tmp;
}
void reset()
{
this_type().swap(this);
}
void reset(T* p)
{
this_type(p).swap(this);
}
private:
T* ptr;
CliScopedPtr(CliScopedPtr%); // disabled
CliScopedPtr% operator=(CliScopedPtr%); // disabled
};
Credit goes to boost::scoped_ptr for the idea.
Example:
class Unmanaged { };
CliScopedPtr<Unmanaged> ptr(new Unmanaged);
Tom