tags:

views:

92

answers:

3
DECLARE_PTR(VIDEOINFOHEADER, pvi, pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER)));
ZeroMemory(pvi, sizeof(VIDEOINFOHEADER));

//initialize Vih
VIDEOINFOHEADER Vih;
Vih.aaa = xxx;
Vih.bbb = yyy;
...
//now how to copy the value of Vih to pvi?

Anyone knows?

+2  A: 

You should be able to do a simple assignment:

*pvi = Vih;

If the class designer has done their job right, then this ensures a usable copy of the value (invoking the assignment operator - there should also be a copy constructor and a probably non-trivial destructor too). If the class designer has botched the job, get a better class library (or educate the class designer).

Your piecemeal initialization of Vih suggests that there may be class design problems. Constructors are intended to initialize classes, and if the class has many publicly visible components, there may be many problems lurking in the wings.

You should probably also be using new to allocate the pvi, and hence a constructor there; you should almost certainly not be using ZeroMemory() to zap the newly allocated variable. Your language tag is 'C++`; the code suggests (not singularly well written) C thinking - not C++ thinking.

If you are the class designer, you need to review some of the fundamentals of class design.


What classes can be copied by assignment?

Two sets of classes can be copied by assignment without fear.

  1. Classes containing simple non-pointer data elements - POD or 'plain old data' classes. These classes can use the assignment operator crafted by the compiler. As soon as you have pointers around, though, you have to start worrying. However, if the class has (non-POD) members which have a valid assignment operator, then you can still use the the default assignment operator crafted by the compiler.

  2. Classes with a properly crafted assignment operator. Here, the class designer deals with all the issues involved in making a copy of the data, duplicating allocated memory or using reference counts and copy-on-write (CoW) techniques to minimize the work. Such classes also have a properly crafted copy constructor - and almost invariably a destructor. The classes are designed to make it easy to do the assignment and pass values to functions, etc.

Classes containing pointers without an explicit assignment operator (and copy constructor, and destructor) have to be examined on their merits. Sometimes, it is OK to copy such classes; more usually, it is not.

Jonathan Leffler
But I need to modify `Vih` afterwards.My code is just a simplified example.
@user198729: And you should be able to modify Vih by using appropriate methods - provided by the class.
Jonathan Leffler
@Jonathan Leffler,can you elaborate on what kind of data structures can be copied by assignment and what not?
This "class" isn't designed for C++, it's designed as a C struct but used from C++. Educating the author probably isn't an option, said author being Microsoft, but I don't know DirectShow, so there might be a more C++-ish interface.
Steve Jessop
@Steve: ugh; I hate having to educate Microsoft. I've signally failed every time I've needed to, ever since 1983. Of course, it would have helped if they spelled Windows as U-N-I-X from the start.
Jonathan Leffler
@user198729: C structs can always be copied by assignment. Classes written for C++ can't be copied by assignment if the author has deliberately disabled that functionality, which you sometimes do when it's just not appropriate or possible to clone a particular object. Sometimes there's a bug in the class, and copying compiles and does *something* but doesn't actually "work". That's "botching the job".
Steve Jessop
@Jonathan: yes, the problems started with backslash as a path separator, and never really picked up from there. I've heard good things about C#.NET, though, so the first 20 years might have been a cunning plan to set people up not to *want* to use C or C++ on Windows any more.
Steve Jessop
@Steve: they succeeded here; I spent time programming DOS back in the early 80s and have never wanted to repeat the experience - and I've been successful in not having to. 'Small model' only C compilers and large graphics programs didn't mix.
Jonathan Leffler
Why not use `ZeroMemory`,it exists for a reason,doesn't it?
wamp
@wamp: In C++ structures, it is dangerous to zero the memory - you might be trampling over important control information, such as the vtable or offsets for virtual base classes or other internal control information for a class. In C, it 'works' - setting all bytes zero. That is not guaranteed to zero `float` or `double` values; in theory, people will tell you it doesn't guarantee that pointers are nulled either, although in practice it almost always works as desired. (The question title mentions C but the tags only mention C++; I'm addressing the question as tagged.)
Jonathan Leffler
A: 

You're using the Windows API from C++. That's possible, but you need to understand the subtle risks you'll be facing.

Many Windows API's use simple structures, and this is no exception. The VIDEOINFOHEADER struct is merely a sequence of simple members. You don't need the difficult syntax. The following code is clearer:

  VIDEOINFOHEADER *pvi = pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
  // Equivalent to
  // DECLARE_PTR(VIDEOINFOHEADER, pvi, pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER)));
  ZeroMemory(pvi, sizeof(VIDEOINFOHEADER));

  pvi->rcSource.left = 5; // etcetera. You can directly assign to pvi->
MSalters
A: 

In C++, you can simply assign one struct to another:

*pvi = Vih;

In C, you would use memcpy

memcpy(pvi,&Vih,sizeof(VIDEOINFOHEADER));

In your particular case, why are you initializing the intermediate Vih object?

After you have decleared and allocated the pvi pointer, you can just go

pvi->aaa = xxx;
pvi->bbb = yyy; 
...

and so on to initialize the videoinfoheader. If that -> syntax is onerous, then you could create a temporary reference to the pointed to data:

DECLARE_PTR(VIDEOINFOHEADER, pvi, pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER)));
ZeroMemory(pvi, sizeof(VIDEOINFOHEADER));

//initialize pvi, using a temporary reference that allows the convenient . notation
VIDEOINFOHEADER& Vih = *pvi;
Vih.aaa = xxx;
Vih.bbb = yyy;
...
// pvi is now initialized as pvi and Vih are both referencing the same memory, just
// using different syntaxes.
Chris Becke