8

I have a class which stores an array and I need to write a method to return a pointer to that array so that other objects can access/modify it.

In an old version of my program, I did that by defining the array in C style. I.e, having a private element bool* list and then allocating memory in the constructor (and liberating that in the destructor). The method then was very simple:

bool* MyClass::getList() {
    return list;
}

Now, I have decided to rewrite the code and use std::vector<bool> instead of the classical array. The problem is that I have also modified the above method as:

bool* MyClass::getList() {
    return &(list[0]);
}

which seems to be the standard way of converting a C++ vector to C array. However, I cannot compile my code, I get the following error:

error: taking address of temporary [-fpermissive]
error: cannot convert ‘std::vector<bool>::reference* {aka std::_Bit_reference*}’ to ‘bool*’ in return

Could anyone help me out with this and tell me what shall I do?

(I have also read that another alternative is to use list.data() as the pointer but this would work only with the newest version of C++ compilers. I am not sure if this is a good idea or not).

6
  • 9
    Remember that std::vector<bool> is a specialization of std::vector, which doesn't work quite like a normal vector. See e.g. this reference. Commented Aug 15, 2013 at 12:44
  • Oh! Thanks for your remark. I guess the problem is that it does not necessarily store its data in a single contiguous chunk of memory. So what is the solution? (In principle, I am not insisting on using a pointer (bool*) as the interface for accessing the list. I just thought this would require least modifications on the other parts of the code). Commented Aug 15, 2013 at 12:48
  • You can always allocate a new "array" on the heap, copy from the vector to the array, and return the array. But then the caller have to free the array. Commented Aug 15, 2013 at 12:54
  • Thanks, but as the list is quite big I don't want to waste time on copying. Commented Aug 15, 2013 at 13:30
  • It's just a single function call. And it's only going to be noticeable if you have more than several hundred of thousands of entries in the vector. Commented Aug 15, 2013 at 13:51

5 Answers 5

10

Your course of thinking is right in general and taking a pointer of the first element would have been sufficient. However, std::vector<bool> is not really a vector of bools as it is being implemented as a bit set. There is a general consensus among the C++ Standard Committee and the Library Working Group that vector<bool> should be deprecated and subsequently removed from the standard library, while the functionality will be reintroduced under a different name. But for now it is still there.

Getting back to your problem, you cannot really interpret a bitset as array of booleans. Therefore, there are two possible ways to go about this:

  1. Replace std::vector<bool> with one of the alternatives that would give you the right behavior.
  2. Convert std::vector<bool> to a C array manually when you need it. For example, you can use size() to pre-allocate memory, then iterate over a vector and fill our your array.

Hope it helps. Good Luck!

Sign up to request clarification or add additional context in comments.

Comments

4
bool* MyClass::getList() {
    return &(list[0]);
}

This will work with any type, but std::vector<bool> has special implementation, where 8 elements are stored in 1 byte, so it doesn't seem possible to take raw pointer to it.

Comments

0

try string.copy():

bool array[100];
std::vector<bool>;
std::copy(vector.begin(), vector.end(), array);

2 Comments

This is very prone to buffer overflow attacks, and the resultant array can't be used as a return value.
@HampusNilsson That's the reason vectors are better.
0

std::vector<bool> uses an internal model where each bool is stored as a single bit. This means it's not a plain C array internally as you would like and you can't convert it to one effortlessly.

Either replace std::vector<bool> with std::deque<bool> and don't use the deque parts, this will give the expected behaviour.

The other solution is to use a std::vector<char> instead and treat the values as bools. This will give the expected behaviour as long as you cast the values properly when accessing it.

1 Comment

std::deque storage is chunked, you can't return a pointer to it.
0

std::vector<bool> isn't a true container of bool values, it's a space-optimized bitfield using proxy reference, not actual bool&.

So when you write &list[0], you're taking the address of a temporary proxy object, not a real bool, which is invalid and causes the compile-time error.

A practical solution is to replace std::vector<bool> with std::vector<uint8_t>, like:

std::vector<uint8_t> list;

uint8_t* MyClass::getList(){
    return list.data();
}

1 Comment

Probably want std::vector<std::uint_least8_t> for a portable solution.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.