简体   繁体   中英

How can a function modify a parameter passed in by value in C++?

Basically this is a question about semantics. I'm using Cereal library for (de)serialization in C++, and found its coding style interesting:

cereal::PortableBinaryInputArchive ar(instream);
int out;
ar(out);
// int is successfully deserialized from input stream here.

The tricky part is that I do not pass in the "out" by reference and ar() can still modify its value. Well in fact, the author just overrides the operator "()". And I found the corresponding lines in the source files.

OutputArchive & operator=( OutputArchive const & ) = delete;

  //! Serializes all passed in data
  /*! This is the primary interface for serializing data with an archive */
  template <class ... Types> inline
  ArchiveType & operator()( Types && ... args )
  {
    self->process( std::forward<Types>( args )... );
    return *self;
  }

I'm quite at a loss, especially the first line ("= delete") and things regarding "std::forward( args )...". I only saw some cases in which macros like va_arg are used and it's the first time that I've encountered something like this. Besides, what does "&&" stand for? Could anyone throw some light upon it?

I'm quite at a loss, especially the first line ("= delete")

The "= delete" effectively ensures that operator= (the assignment operator...) cannot be called, and that the default (assignment operator) shall not be generated. It is the same making operator= private, and not providing a definition. This operator can also be used for normal functions, in which case it's use is prohibited similarly (Refer c++ 11 standard, section 8.4.3):

struct B
{
  void foo(){}
};

struct D : B
{
  void foo() = delete;
};

int main() {
    D().foo(); //Fails to compile here - deliberate!!!
    return 0;
}

Note that the type on which foo is called is important. It could still be called on the base type, just like one could still slice even though derived assignment is prohibited (see example below):

struct B{};

struct D : B
{
  D& operator=(const D&) = delete;    
};

int main() {
    B b;
    D d1, d2;
    b = d1; //Compiles fine - slices
    d1 = d2; //Fails to compile...
    return 0;
}

and things regarding "std::forward( args )...".

std::forward allows perfect forwarding of arguments (ie the types of arguments wrt to r/l valueness and modifiers don't change (Refer) .

I only saw some cases in which macros like va_arg are used and it's the first time that I've encountered something like this.

template <class ... Types>
void foo( Types&& ...);

The ... in this context is referred to as variadic templates (google).

Besides, what does "&&" stand for? Could anyone throw some light upon it?

&& stands for either rvalue reference, or universal reference, depending on context. In this case it's a universal reference (Scott Meyers has a good article on universal references here ).

EDIT: Universal references are correctly called forwarding references now (n4164) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM