## C++ bindings for libpmemobj (part 1) - pmem resident variables

One of the biggest hurdles and error prone things about our C API is that the user has to manually keep track of modifications to the persistent memory resident variables while in a transaction. A special semi-transparent template property class has been implemented to automatically add variable modifications to the transaction undo log.

### pmem::obj::p

Let’s start with the vector example from the previous tutorial series. It looked like this:

``````struct vector {
int x;
int y;
int z;
}

PMEMoid root = pmemobj_root(pop, sizeof (struct vector));

struct vector *vectorp = pmemobj_direct(root);
TX_BEGIN(pop) {
vectorp->x = 5;
vectorp->y = 10;
vectorp->z = 15;
} TX_END
``````

As you can see, the programmer has to remember to call `pmemobj_tx_add_range` function before any modifications to the memory. In a simple case like this one it might not be such a big deal, but once the code gets complex it may lead to some difficult to find consistency issues.

By using the C++ API we can simplify this code like so:

``````#include <libpmemobj/p.hpp>

using namespace pmem::obj;

struct vector {
p<int> x;
p<int> y;
p<int> z;
}

PMEMoid root = pmemobj_root(pop, sizeof (struct vector));

struct vector *vectorp = pmemobj_direct(root);
TX_BEGIN(pop) {
vectorp->x = 5;
vectorp->y = 10;
vectorp->z = 15;
} TX_END
``````

The template class `pmem::obj::p` does not add storage overhead. The size of the vector structure is exactly the same as in the C version.

This mechanism works overriding `operator=` and adding the memory to the undo log before modification. It’s pretty straightforward.
{"ft_lang_label":"__label__en","ft_lang_prob":0.8015982,"math_prob":0.8926347,"size":1665,"snap":"2022-27-2022-33","text_gpt3_token_len":420,"char_repetition_ratio":0.13666466,"word_repetition_ratio":0.14671814,"special_character_ratio":0.24444444,"punctuation_ratio":0.14556962,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.955155,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2022-08-17T04:02:04Z\",\"WARC-Record-ID\":\"<urn:uuid:47b599f6-f169-42ca-917a-ea4c34f6d3bb>\",\"Content-Length\":\"27715\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:d4b2053a-6648-477b-99bf-9d9f838896bf>\",\"WARC-Concurrent-To\":\"<urn:uuid:c8f3efce-ab81-41cc-9162-6d6e193897f6>\",\"WARC-IP-Address\":\"185.199.109.153\",\"WARC-Target-URI\":\"https://pmem.io/blog/2016/01/c-bindings-for-libpmemobj-part-1-pmem-resident-variables/\",\"WARC-Payload-Digest\":\"sha1:PWGU2Q2KNRELRZQSMNZ7TQYMD6QESNH4\",\"WARC-Block-Digest\":\"sha1:AD7X4YBZDMJLT2FYUOZ24XHHS2U437OJ\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2022/CC-MAIN-2022-33/CC-MAIN-2022-33_segments_1659882572833.95_warc_CC-MAIN-20220817032054-20220817062054-00509.warc.gz\"}"}