johnbakers
johnbakers

Reputation: 24770

Does a vector behave the same was as an array when dealing with pointers?

Is the name of a vector simply a pointer, just like a vanilla C array?

Thus, I could send the address to a single piece of non-vector data (a pointer, in other words) to a function argument that expects a vector since a vector is also a pointer.

For example, a function that is declared as this:

void RenderingEngine::Render(const vector<Visual>& visuals) const{

Could be called like this:

Visual visual; // is NOT a vector
//do stuff with visual
m_renderingEngine->Render(&visual); 

Makes sense and is valid, legal C++?

This example code is from an O'Reilly C++ book, so I guess it is an error in the book.

Upvotes: 0

Views: 177

Answers (4)

jdm
jdm

Reputation: 10070

The other answers are correct, but I'd like to add that it works the other way around:

void RenderingEngine::Render(Visual *visuals, size_t n_visuals);

Can be called like this:

vector<Visual> visuals;
m_renderingEngine->Render(&visuals[0], visuals.size());

You just take the address of the first element and pass it as if it was an array. This works because the elements of a vector are laid out sequentially in memory. (As pointed out in the comments, shouldn't use this in new code, of course. It's safer and easier to define you method to take a vector. However, if you already have a legacy function that takes a pointer, this allows you to use vectors in your own code.)


The reason it works this way around, but not the way in your question (pass a pointer, to a function that takes a vector), is that in your case it can't determine the size of the array at runtime. But it has to know the size to construct the vector:

// (wrong code)
// Passing one element:
Visual visual;
m_renderingEngine->Render(&visual);

// Passing two elements, how does Render know that
// there are two elements at that address?
Visual[2] visuals;
m_renderingEngine->Render(&visuals[0]); 

As Nawaz pointed out, you can do something similar in C++11:

Visual visual;
m_renderingEngine->Render( {visual} ); // C++11

You can also put more elements in the {}. This only works because the compiler can tell at compile-time how many elements there will be. It's just syntactic sugar for:

vector<Visual> myVec = {visual};  // C++11
m_renderingEngine->Render(myVec);

which in turn works like the classic:

vector<Visual> myVec;
myVec.push_back(visual);
m_renderingEngine->Render(myVec);

(although the C++11 version might be slightly optimized, I don't know for sure).

Upvotes: 1

Puppy
Puppy

Reputation: 146940

No, it isn't, which is rather fortunate because the behaviour of C arrays is abominable. If you find yourself looking for it, I would suggest instead looking for some new learning material w.r.t. C++.

Upvotes: 1

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361482

No. That doesn't make sense. There is no implicit conversion from T* to std::vector<T>.

But in C++11, you can do something which is very close1 to what you're doing. You could create the vector on the fly while passing the argument as:

m_renderingEngine->Render( {visual} );  //note the curly braces!

With that you create a vector object out of the expression {visual} which then gets passed to the function.


1. very close in the sense that you just have to type one more character to make your code work. Instead of typying &, just type {, and one more } at the end. That is it. Life is so easy with C++11.

Upvotes: 1

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272517

Is the name of a vector simply a pointer, just like a vanilla C array?

No. It's a fully-formed class.*


* What's more, a vanilla C array is not a pointer either (it just get turns into one in most situations).

Upvotes: 2

Related Questions