3

Sorry if "new call" isn't a C++-term. If it is not, tell me what's the right term. I'm a C programmer starting with C++. I have struct A that I want to initialize it using paramereters in new operator. Like this:

A* a = new A(foo, baa);

So, I tried to use it defining function: void* A::operator new(T a, T B) { ... }

But I get an compiler-error:

error: 'operator new' takes type size_t ('unsigned int') as first parameter

Also, not sure if it's relevant but the function that overload parameter of size_t type is already defined, like this:

void* A::operator new(size_t size) { ... }

Kara
  • 6,115
  • 16
  • 50
  • 57
The Mask
  • 17,007
  • 37
  • 111
  • 185
  • The best way to make that would be `A a(foo, baa);`, but you don't need to provide a `new` overload; there's already one built in. – chris Jan 20 '14 at 21:41
  • 2
    Do you wish to overloading `operator new` (creating your own memory allocator) or do you simply want to give `A` a constructor that takes two arguments...? – TypeIA Jan 20 '14 at 21:42
  • @chris: just like an usual method? another question but related: Will this method be able to return type different to `A*` and `void*`? – The Mask Jan 20 '14 at 21:44
  • @dvnrrs: The last option: `A` a constructor that takes two arguments... sorry if I'm was not clear enough. – The Mask Jan 20 '14 at 21:45
  • @TheMask, It's probably worth reading something like Bjarne's short "Tour of C++" to quickly get into it from C. – chris Jan 20 '14 at 21:49
  • 2
    Hmm, I've been upvoting the question, because in the whole view (with all of the current 3 answers), it makes a good picture for a renegade c programmer, what's the difference of overloading `new()` vs writing a constructor. Could be a candidate for a canonical if merged alltogether. – πάντα ῥεῖ Jan 20 '14 at 22:18

3 Answers3

5

You don't need to overload operator new for this. You just want a constructor:

class A
{
    public:
        A(FooType foo, BaaType baa);
};

A::A(FooType foo, BaaType baa)
{
    // initialize object here
}

You can then write (assuming you have obtained a variable foo of type FooType and so on):

A *a = new A(foo, baa);
TypeIA
  • 16,916
  • 1
  • 38
  • 52
  • I will try it. Will it work for `struct` too, right? I don't how many different are C++ `class` and `struct`. Anyway, thanks – The Mask Jan 20 '14 at 21:48
  • 1
    @TheMask `class` and `struct` are completely equivalent in c++, the only difference is the default member protection policies. – πάντα ῥεῖ Jan 20 '14 at 21:50
  • 1
    @TheMask It will work for a `struct`. They are *almost* identical in C++. (The only differences in C++ are that in a `class` members are private by default; in a `struct` they are public by default; and an inherited `struct` is public by default while an inherited class is private.) – TypeIA Jan 20 '14 at 21:50
4

The way it's done in C++ is by having a non-default constructor for A.

struct A {
  int a;
  int b;
  explicit A(int a_, int b_) : a(a_), b(b_) {}
};

...
A * a = new A(1, 2);
assert(a->a == 1);
assert(a->b == 2);

The expressions after the colon (:) are the constructor's initialization list - they perform initialization of the members during construction. They are usually more efficient than the more C-style variant:

A::A(int a_, int b_) { a = a_; b = b_; }

In idiomatic C++, you always want to use the initialization lists where possible. You also do not want to use naked pointers, so it'll be better to write:

std::shared_ptr<A> a(new A(1, 2));
// or
std::unique_ptr<A> a(new A(1, 2));

The shared_ptr is for when multiple entities may need to hold the instance and there's no clear scope where it should exist. The unique_ptr is for when there's a clear scope where the object should exist. The unique_ptr will delete a when it goes out of scope. The shared_ptr will perform the deletion when the last shared_ptr referencing given object goes out of scope.

The reason to use the explicit keyword is to prevent the use of given constructor in automatic conversions. In pre-C++11 times, it had no effect on multi-argument constructors. But in C++11, it has effect when you use brace intialization.

Community
  • 1
  • 1
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • @πάνταῥεῖ Why +1 for that? It's probably just going to confuse the OP. One step at a time. He hasn't even figured out constructors yet. – TypeIA Jan 20 '14 at 21:51
  • @dvnrrs Because `explicit` was worth being mentioned with the 1st version of the answer (and still is of course). The actual version might confuse an inexperienced c -> c++ adept, but I don't have the feeling the OP is one ... (I've been upvoting your answer as well BTW) – πάντα ῥεῖ Jan 20 '14 at 21:57
  • @KubaOber Your answer looks best to be edited for giving a canonical answer to the OP's problem/misunderstanding. You might integrate the aspects from the other answers to yours, and upvote for contribution. – πάντα ῥεῖ Jan 20 '14 at 23:08
3

You need to distinguish between the new operator and the constructor: The new operators do nothing more or less than malloc(), they allocate a slap of memory. A constructor then initializes that slap of memory to make it a valid object of type A.

The confusion for you arises from the fact, that the new keyword does both, allocation and construction. The line

A* foo = new A(...);

first calls a new operator to get the memory, then it calls the appropriate constructor, passing it the given arguments, to construct the object.

So, as the others have already pointed out, you need to add a constructor with your desired arguments, not a new operator:

class A {
public:
    A(int arg1, int arg2);
    int member1, member2;
};

A::A(int arg1, int arg2) : member1(arg1), member2(arg2) {
    //Do additional stuff that cannot be achieved by calling the constructors of the members alone.
}

Note, that in this code, you explicitly call the constructors of the data members of A in the initializer list (the part between the : and the {.

cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106
  • `new` is totally different from `malloc`; it calls the type's constructor, `malloc` does not. (I'm sure this is what you meant but we need to be careful not to mislead the OP who is obviously just starting out.) – TypeIA Jan 20 '14 at 21:52
  • @dvnrrs Sorry, but you are wrong. All `operator new()` definitions only provide memory. They do not even get the required arguments to call a constructor. The effect is truly that of a `malloc()` plus that exception thing. The only advantage of `operator new()` within a class is, that you can use different methods for allocation for objects of different class. – cmaster - reinstate monica Jan 20 '14 at 22:03
  • @dvnrrs _'A constructor then initializes ...'_ He's mentioning the difference correctly (check [placement new](http://en.wikipedia.org/wiki/Placement_syntax)). – πάντα ῥεῖ Jan 20 '14 at 22:05
  • @cmaster Yes, I realize a user-defined `operator new` overload does not call the ctor directly. But from a user's perspective, using `new` causes the ctor to be called, **unlike malloc**. – TypeIA Jan 20 '14 at 23:03
  • @cmaster **[resistance is futile, ...](http://en.wikipedia.org/wiki/Borg_%28Star_Trek%29#.22Resistance_is_futile.22)** ;) – πάντα ῥεῖ Jan 20 '14 at 23:29