Basically, I have the following situation. Note: void* is used to denote arbitrary data, it is strongly typed in a real application.
class A
{
public:
//uses intermediate buffer but doesn't change outward behavior
//intermediate buffer is expensive to fill
void foo(void* input_data);
//uses intermediate buffer and DOES explicitly change something internally
//intermediate buffer is expensive to fill
void bar(void* input_data);
//if input_data hasn't changed since foo, we can totally reuse what happened in foo
//I cannot check if the data is equal quickly, so I allow the user to pass in the
//assertion (put the honerous on them, explicitly tell them in the comments
//that this is dangerous to do, ect)
void bar(void* input_data, bool reuse_intermediate);
private:
void* intermediate_buffer_;
void* something_;
};
So trying for const correctness, intermediate_buffer_ is never exposed so it sortof fits the definition for using a mutable variable. If i never reused this buffer, or I checked for equal input_data before using the cached values, that would be the end of the story, but because of the reuse_intermediate I feel like I'm half exposing it, so I'm not sure whether or not the following makes sense.
class A
{
public:
//uses intermediate buffer but doesn't change something
//intermediate buffer is expensive to fill
void foo(void* input_data) const;
//uses intermediate buffer and DOES explicitly change something internally
//intermediate buffer is expensive to fill
void bar(void* input_data);
//if input_data hasn't changed since foo, we can totally reuse what happened in foo
//I cannot check if the data is equal quickly, so I allow the user to pass in the
//assertion (put the honerous on them, explicitly tell them in the comments
//that this is dangerous to do, ect)
void bar(void* input_data, bool reuse_intermediate);
//an example of where this would save a bunch of computation, though
//cases outside the class can also happen
void foobar(void* input_data)
{
foo(input_data);
bar(input_data,true);
}
private:
mutable void* intermediate_buffer_;
void* something_;
};
Thoughts?
I think this is improper use of mutable. In my experience mutable is used for ancillary private member variables that by their very nature can not be declared const, but do not modify the "conceptual constness" of the public interface.
Take for example a Mutex member variable and a 'thread-safe getter':
class Getter {
public:
Getter( int d, Mutex & m ) : guard_( m ), data_( d ) { };
int get( ) const { Lock l(guard_); return data_; };
private:
mutable Mutex guard_;
const int data_;
};
The main point here is that the data declared mutable (in this case the guard) does change (it's locked and unlocked) but this has no impact on constness from the users perspective. Ultimately, despite the mutable Mutex, you still can't change the const data_ member variable and the compiler enforces this.
In your case, you really want the intermediate_buffer to be const but you explicitly tell the compiler it's not by declaring it mutable. The result is that you can change the data and the compiler can't do a thing about it.
See the difference?
If you really want the interface to live up to the const agreement, make it explicit via something like this:
class A {
public:
A( void* input_data );// I assume this deep copies.
void foo() const;
void bar();
private:
const void* intermediate_buffer_;
void* something_;
};
Now the onus is truly on the user and enforced by the compiler regardless of what the comments say and without any use of mutable. If they know that input_data has changed, they'll have to create a new one, preferably const.
Instead of hiding the intermediate object inside the const object, expose it and let foo and bar return a copy. You are making it very explicit that the intermediate object is being shared, and providing a new capability to keep more than one on hand. If you want to hide the implementation details you can expose an empty class and make the intermediate object a child of this base class.
class A
{
public:
class Intermediate
{
//empty
};
//uses intermediate buffer but doesn't change outward behavior
//intermediate buffer is expensive to fill
//if cache_ptr is NULL the intermediate buffer is discarded
void foo(void* input_data, Intermediate** cache_ptr = NULL) const;
//uses intermediate buffer and DOES explicitly change something internally
//intermediate buffer is expensive to fill
void bar(void* input_data, Intermediate** cache_ptr = NULL);
private:
class IntermediateImpl : public Intermediate
{
//...
};
void* something_;
};
To answer your question directly.
If the function foo is const, calling it at any time should never alter the result of the next operations.
for example:
A a(some_big_data);
a.bar(some_big_data, true);
should give exactly the same result as (excluding performance differences)
A a(some_big_data);
a.foo(some_different_big_data);
a.bar(some_big_data, true);
Since foo is const, users will expect the result to be the same.
If this is the case then making the buffer mutable is reasonable.
Otherwise, it is probably wrong.
Hope this helps
Disclaimer: I am not advocating the use of void* with my answer, I hope that this was simply for demonstration purposes and that you don't actually need to use it yourself.
If a lot of computations can be saved when reusing the same input data, then make input_data a member variable.
class A
{
public:
A(void * input_data)
{
set_input_data(input_data);
}
//Note, expensive operation
void set_input_data(void* input_data)
{
this->input_data = input_data;
fill_intermediate_buffer();
}
void foo() const;
void bar() const;
private:
void * input_data;
void * intermediate_buffer;
void * something;
};
This is just an outline obviously, without more details about what input_data, intermediate_buffer and something are or how they get used or shared a lot of details will be missing. I would definitely drop the pointers from the implementation and use std::vector. This is especially true of input_data, where you would want to store a copy of the passed-in buffer. Consider:
A a(input);
//modifiy input
a.foo();
You will likely get the wrong result from using a mismatched input_data/intermediate_buffer pair.
Also note that if you don't actually need input_data for foo and bar then you can drop the void* input_data from the class, but still keep the constructor and setter that refer to it.
I'd say that your use of mutable does make some amount of sense - but that it is incorrect, and possibly dangerous. If you make a function const it needs to be just that.
Imagine if you use your class in a multithreaded program, with several threads operating on the same instance of the class - for example:
thread1:
while(1) {
(...) //do some work
sharedA->foo(thread1Data);
sharedA->bar(thread1Data, true);
(...) //do some more work
sharedA->bar(thread1Data, true);
(...) //do even more work
}
thread2:
while(1) {
(...) //do some different work, maybe wait for an event
sharedA->foo(thread2Data);
(...) //sleep for a bit
}
Since thread2 is calling a const function, it shouldn't have any influence at all on the output of calling bar from thread1 - but if the timing is right (or wrong!) it will - and due to those reasons I'd say it's wrong to use mutable to make foo const in this case, even if you're only using the class from a single thread.
Given that you can't check input_data for equivalence, you could perhaps take a cryptographic hash of it and use that for the comparison. This would eliminate the need for the reuse_intermediate flag.
mutable is used to override the const-ness of a variable or data member.
Example:
Class A
{
public:
int m;
}
void foo(const A& a);
In the example above, function foo would be allowed to modify a.m even though you pass a const reference.
In your example I don't think you need to use mutable - it can lead to very bad designs - since you will write to that buffer.
Related
I have a C++ class A that can be constructed to perform a certain computation using a function A::compute . This function requires to write to a preallocated memory area (working area) that was allocated at construction of A to perform this computation efficiently. I would like to A::compute to be const in relation to the class, because the computation does not alter the logical state of the object.
Is this a case when the keyword mutable should be used?
Example code:
class A {
public:
A(size_t size) : m_workingArea(size) {}
int compute(const std::vector<int>& data) const {
// ... checks ...
std::copy(data.begin(), data.end(), m_workingArea.begin());
// ... compute ...
// return a result, say first element of the working area
return m_workingArea[0];
}
private:
mutable std::vector<int> m_workingArea;
};
It is perfectly reasonable to use mutable in this case.
While it is not physically const, the compute(...) method is logically const. That is, to an outside user, compute(...) leaves the object unchanged, despite any internal changes.
Here in the isocpp.org FAQ, the Standard C++ committee recommends that we should prefer logical const over physical const.
Given this, it makes sense to mark m_workingArea mutable, so that compute(...) can be const and logical const-correctness can be maintained. The effect of this should be a clear user interface and clearly stated programmer intent.
To me it looks like a misuse since you are changing the object, but if you really want a fixed size area that you can modify even when this is const, you could keep a pointer to that area and then you don't need to make it mutable:
#include <memory>
#include <vector>
class A {
public:
A(size_t size) : m_workingArea(std::make_unique<int[]>(size)) {}
int compute(const std::vector<int>& data) const {
// ... checks ...
std::copy(data.begin(), data.end(), m_workingArea.get());
// ... compute ...
// return a result, say first element of the working area
return m_workingArea[0];
}
private:
std::unique_ptr<int[]> m_workingArea;
};
I have some code that's accumulated a lot of cruft over many years. It has a class that looks like:
class Foo {
public:
Foo(int* data) : data_(data) { }
Foo() : data_(nullptr) { }
void loadFile(File* file);
private:
const int* data_;
};
void Foo::loadFile(File* file) {
file->loadToBuffer(const_cast<int**>(&data_));
}
void File::loadToBuffer(int** buf) {
*buf = new int[1024];
// Load the data...
}
I believe that the const member was originally used "properly" and initialized in the constructor, but over time other ways to initialize the object were added that didn't fit that pattern so the const_cast was used as a workaround. The actual class is very large (many thousands of lines) and the initialization is complicated enough that it's not possible to factor it out in a way that respects the const.
As far as I know this is undefined behavior, and so it should be killed with fire by removing the const qualifier on data_. But this code has been kicking around for a long time without causing any obvious problems, so I'm not sure if there's something I'm missing --- is this (mis)use of const ever acceptable, in theory or in practice? Are there any conceivable benefits to writing something like this, or is it just a happy accident that it hasn't broken yet?
This is a pointer to const int, it can point either to an int or to a const int
const int* data_;
You can change data_ (you can direct it to point to another int/const int)
You cannot change *data_ (you cannot change the pointed value)
When you do a static_cast on it, it is allowed ONLY if data_ points to an int without const. static_cast in case data_ points to const int would cause undefined behaviour.
So in this case the code is fine because data_ will only point to int (and not const int), either with Foo first constructor or in loadToBuffer.
Is there a way to tell if an instance has been constructed in temporary scope or not, or prevent it from being used outside of temporary scope? I'm guessing there's not, but then again, I'm always surprised by the ability of C++ to exceed its own design limitations.
It's kind of a weird question, I admit, and I don't know how to "justify" the desire short of just providing the backstory.
The question arises from a shuttle class we use to glue together a scary number of legacy systems, each with their own notion of how data is represented. For a familiar example, take strings. We could overload each method in our API with each "style" of string:
void some_method(const char* arg);
void some_method(const std::string& arg);
void some_method(const QString& arg);
void some_method(const XmlDocString& arg);
void some_method(const wire_string& arg);
Or we could do:
void some_method(const StringArg& arg);
Where that helper class is (let's ignore string encodings for now and just assume bad old C-style strings for the purposes of this question):
class StringArg {
public:
StringArg() : m_data(""), m_len(0) {}
template<size_t N>
StringArg(const char (&s)[N]) : m_data(s), m_len(N-1) {}
StringArg(const char* s) : m_data(s?s:"") { m_len = strlen(m_data); }
template<class T>
StringArg(const T& t) : m_data(data_from(t)), m_len(len_from(t)) {}
const char* data() const { return m_data; }
const char* size() const { return m_len; }
private:
const char* m_data;
size_t m_len;
};
const char* data_from(const std::string& s) { return s.c_str(); }
size_t len_from(const std::string& s) { return s.size(); }
template<class XmlType>
const char* data_from(const XmlString<XmlType>& s) { return &s.content()[0]; }
template<class XmlType>
size_t len_from(const XmlString<XmlType>& s) { return s.byte_length(); }
ADL chooses the various data_from()/len_from() to get us a buffer backed by something else and its size. In reality there's extra metadata to capture important information about the nature of the buffer and how to iterate it, but the important point for this discussion is that StringArg is used in temporary scope, is cheap to copy, provides fast access to some buffer backed by something else on the outside of the interface whose type we now don't actually need to care about, and that any conversion, argument checking, or length calculations are done once at the boundary.
So there we are, someone is free to call it with two wildly different string classes:
interface_method(header() + body.str() + tail(), document.read().toutf8());
We don't need to care about the lifetime or the type of whatever's going on here, and internally we can pass around pointers to those buffers like candy, slice them up, parse them, log them in triplicate, without accidental allocation or lengthy memory copies. As long as we never hang on to those buffers, internally, this is safe and fast and has been a joy to maintain.
But as this API becomes more widely used, StringArg is (perhaps unsurpisingly) being used in places other than temporary scope, as if it were Yet Another String Class, and the resulting fireworks are impressive. Consider:
std::string t("hi");
write(StringArg(t+t)); //Yes.
StringArg doa(t+t); //NO!
write(doa); //Kaboom?
t+t creates a temporary whose content StringArg will point into. In temporary scope this is routine, nothing interesting to see here. Outside of it, of course, it's insanely dangerous. Dangling pointers to random stack memory. Of course, the second call to write() actually will work just fine most of the time, even though it is most clearly wrong, which makes detecting these mistakes quite difficult.
And here we are. I want to allow:
void foo(const StringArg& a);
foo(not_string_arg());
foo(t+t);
I want to prevent or detect:
StringArg a(t+t); //No good
And I'd be fine if the following wasn't possible, too, even though it's fine:
foo(StringArg(t+t)); //Meh
If I could detect the scope this thing was being constructed in, I could actually go and arrange to copy the content into a stable buffer in the constructor, similar to std::string, or throw an exception at runtime, or even better, if I could prevent it at compile time that'd ensure it was only used as designed.
Really, though, I only want StringArg to ever be the type of a method argument. An end user will never have to type "StringArg" in order to use the API. Ever. You'd hope that'd be easy enough to document away, but once some code looks like it works, it multiplies, and multiplies...
I have tried making StringArg non-copyable but that doesn't help much. I have tried creating an additional shuttle class and a non-const reference to try and fake out the implicit conversions in such a way they go my way. The explicit keyword seems to make my problem worse, promoting the typing of "StringArg". I tried messing around with an additional struct with partial specialization which is the only thing that knows how to construct a StringArg, and hiding the constructors for StringArg... something like:
template<typename T> struct MakeStringArg {};
template<> struct MakeStringArg<std::string> {
MakeStringArg(const std::string& s);
operator StringArg() const;
}
So then the user has to wrap all arguments with MakeStringArg(t+t) and MakeFooArg(foo) and MakeBarArg(bar)... existing code doesn't compile and in any case it kind of kills joy of using the interface.
I'm not above macro hacks at this point. My bag of tricks is looking pretty empty about now. Anyone have any advice?
So Matt McNabb points out
std::string t("hi");
const StringArg& a = t + t;
This causes a temporary StringArg to live longer than the content it points to. What I actually need is a way to determine when the full expression in which StringArg was constructed has ended. And that's actually doable:
class StringArg {
public:
template<class T>
StringArg(const T& t, const Dummy& dummy = Dummy())
: m_t(content_from(t)), m_d(&dummy) {
m_d->attach(this);
}
~StringArg() { if (m_d) m_d->detach(); }
private:
void stale() {
m_t = ""; //Invalidate content
m_d = NULL; //Don't access dummy anymore
//Optionally assert here
}
class Dummy {
public:
Dummy() : inst(NULL) {}
~Dummy() { if (inst) inst->stale(); }
void attach(StringArg* p) { inst = p; }
void detach() { inst = NULL; }
StringArg* inst;
};
friend class Dummy;
private:
const char* m_t;
Dummy* m_d;
};
With this, Matt's example and all the others I was hoping to prevent are thwarted: when the full expression ends, no StringArg points to anything suspect any longer, so any StringArg "given a name" is guaranteed to be useless.
(In case it's not clear why this works, it's because a Dummy must have been constructed before a StringArg that uses it, and therefore StringArg is guaranteed to be destroyed before the Dummy unless its lifetime is greater than the full expression in which it was constructed.)
I admit I didn't read your entire post, but you seem to have conflicting requirements. On the one hand you state that you want to avoid dangling references, but then you write:
write(StringArg(t+t)); //Yes.
StringArg doa(t+t); //NO!
If your only concern is to avoid dangling references then change the "NO!" to a "Yes", and in both cases move out of the temporary into a local value. The constructor would be:
StringArg(std::string &&arg)
{
this->the_arg = std::move(arg);
}
where the_arg is a std::string.
You could have StringArg store the string when it was constructed from an rvalue, and hold a reference to a string if it was constructed from an lvalue.
If you want a class which methods could be used only by rvalue objects, you could use rvalue qualifier on methods in C++11:
class only_rvalue
{
public:
only_rvalue() = default;
only_rvalue( const only_rvalue& ) = delete;
only_rvalue( only_rvalue&& ) = default;
only_rvalue& operator=( const only_rvalue&& ) = delete;
only_rvalue& operator=( only_rvalue&& ) = default;
void foo() &&;
void bar() &&;
void quux() &&;
};
only_rvalue create();
int main()
{
only_rvalue{}.foo(); //ok
create().bar(); //ok
only_rvalue lvalue;
lvalue.foo(); //ERROR
}
I have a Visual Studio 2008 C++ application where a function Foo::CreateBar uses an internal function to populate a buffer with some data as below. I understand that VS2008 will use return value optimization (RVO) to ensure the Foo::GetData() call will not incur a copy, but will I incur copies for the Bar constructor? How about for returning the Bar object from Foo::CreateBar Is there a more efficient way to do this? Do I need to redefine my Buffer as boost::shared_ptr< std::vector< BYTE > >?
typedef std::vector< BYTE > Buffer;
class Bar
{
public:
explicit Bar( Buffer buffer ) : buffer_( buffer ) { };
// ...
private:
Buffer buffer_;
};
class Foo
{
public:
Bar CreateBar() const { return Bar( GetData() ); };
// ...
private:
static Buffer GetData()
{
Buffer buffer;
// populate the buffer...
return buffer;
};
};
Thanks,
PaulH
You can answer this question for sure by examining the assembler code that's generated for this source - modify the compiler output options to produce a listing interlaced with the source code.
shared_ptr is not appropriate, in any case. That's a device for the programmer to manage designs requiring shared objects efficiently, not to fool the compiler into not constructing more objects than it should.
Using a const reference as parameter of the Bar constructor
explicit Bar( const Buffer & buffer ) : buffer_( buffer ) { };
will surely avoid you the copy caused by the pass-by-value in the constructor call, but you will have a copy in the construction of the buffer_ field.
shared_ptr would work. unique_ptr would work, because ownership is transferred.
You could also use out parameters to avoid the copy. Add a factory function...
class Bar
{
public:
explicit Bar( void (*factory)(Buffer& buffer) ) { factory(buffer_); }
// ...
private:
Buffer buffer_;
};
class Foo
{
public:
Bar CreateBar() const { return Bar( GetData ); }
// ...
private:
static void GetData(Buffer& buffer)
{
// populate the buffer...
}
};
You should make a couple of different tests and see what your compiler does with it. In the code above there are as many as 4 copies of the buffer:
Inside GetData
Return value of GetData
Argument of constructor
Member
The compiler by doing RVO/NRVO can merge 1 and 2 into a single object. Moreover it can merge those two objects with 3 by placing the three objects in the same memory location. What it cannot do is place that object and 4 in the same memory address (in the general case).
On that particular copy, you might elide it by default initializing the internal member vector (usually no cost) and swapping the contents of the argument with the member:
explicit Bar( Buffer buffer ) // pass by value if your compiler optimizes it
: buffer_() // default construct: no cost
{
buffer_.swap( buffer ); // swap: no cost
};
Also note that this is the whole reason for rvalue references in the upcoming standard, in C++0x (I know that is not available in VS08) the compiler will use move semantics to avoid the copies while maintaining the code readable (readable as in closest to the intentions than to tricks to avoid the cost).
You will definitely incur a copy for the buffer.
Why do you want to use a shared pointer? Is it a shared data? If so - then go for it. If not - than you have to copy. We don't really know what is your design, do we?
If you're sensitive to copy operations, you may want to force copy operations to be explicit or even prevent them altogether. If you make the copy constructor and assignment operator protected/private (or use boost::noncopyable) the compiler will produce an error whenever it tries to generate code that copies the object. Of course if you do want to make copies sometimes you'll need to provide a method for explicitly doing so, but that ensures that you never accidentally introduce a copy operation.
I want to implement a Swap() method for my class (let's call it A) to make copy-and-swap operator=(). As far as I know, swap method should be implemented by swapping all members of the class, for example:
class A
{
public:
void swap(A& rhv)
{
std::swap(x, rhv.x);
std::swap(y, rhv.y);
std::swap(z, rhv.z);
}
private:
int x,y,z;
};
But what should I do if I have a const member? I can't call std::swap for it, so I can't code A::Swap().
EDIT: Actually my class is little bit more complicated. I want to Serialize and Deserialize it. Const member is a piece of data that won't change (its ID for example) within this object. So I was thinking of writing something like:
class A
{
public:
void Serialize(FILE* file) const
{
fwrite(&read_a, 1, sizeof(read_a), file);
}
void Deserialize(FILE* file) const
{
size_t read_a;
fread(&read_a, 1, sizeof(read_a), file);
A tmp(read_a);
this->Swap(tmp);
}
private:
const size_t a;
};
and call this code:
A a;
FILE* f = fopen(...);
a.Deserialize(f);
I'm sorry for such vague wording.
I think what you really want is to have an internal data structure that you can easily exchange between objects. For example:
class A
{
private:
struct A_Data {
int x;
int y;
const int z;
A_Data(int initial_z) : z(initial_z) {}
};
std::auto_ptr<A_Data> p_data;
public:
A(int initial_z) : p_data(new A_Data(initial_z)) {}
void swap(A& rhv) {
std::swap(p_data, rhv.p_data);
}
};
This keeps the z value constant within any instance of A object internal data, but you can swap the internal data of two A objects (including the constant z value) without violating const-correctness.
After a good nights sleep I think the best answer is to use a non-const pointer to a const value -- after all these are the semantics you are trying to capture.
f0b0s, a good design principle is to design your objects to be immutable. This means that the object can't change once created. To "change" the object, you must copy the object and make sure to change the elements you want.
That being said, in this case you should look at using a copy constructor instead to copy the objects you want to swap, and then actually swap the references to the object. I can understand it'd be tempting just to be able to change the elements of an object under the hood, but it'd be better to make a copy of the object and replace the references to that object with the NEW object instead. This gets you around any const nastiness.
Hope this helps.
I suggest you use pointers to the instances. The pointers can be swapped much easier than the data in the class or struct.
The only way to swap a constant value is to create another object, or clone the current object.
Given a struct:
struct My_Struct
{
const unsigned int ID;
std::string name;
My_Struct(unsigned int new_id)
: ID(new_id)
{ ; }
};
My understanding is that you want to swap instances of something like My_Struct above. You can copy the mutable (non-const) members but not the const member. The only method to alter the const member is to create a new instance with a new value for the const member.
Perhaps you need to rethink your design.
IMHO you must consider not to swap CONST members.
PD: I think you could consider to use reflection in your approach. so you don't have to maintain the function.
This is why const_cast was created. Just remember not to shoot your foot off.
Edit: OK, I concede - const_cast wasn't made for this problem at all. This might work with your compiler, but you can't count on it and if demons come flying out of your nostrils, please don't blame me.
tl;dr; : It's Undefined Behavior.
Reference/reason: CppCon 2017: Scott Schurr “Type Punning in C++17: Avoiding Pun-defined Behavior, #24m52s +- ”
My interpretation, by example:
Suppose you create an object of type T, which have some const members. You can pass this object as a non-const reference to a function f(&T) that manipulates it, but you'd expect the const members to remain unalterable after the call. swap can be called in non-const references, and it can happen inside the function f, breaking the premise of const members to the caller.
Every part of your code that uses swap would have to assert that the object of type T being swapped does not belong to any context where the const members are assumed constant. That is impossible to automatically verify*.
*I just assumed that this is impossible to verify because it seems like an extension of the undecidability of the halting problem.