简体   繁体   中英

const char& as an argument to a function

I need some clarification on the following blocks of code. I'm working on something similarly coded and I want to understand how it works. There's not a lot of mentions on Google and the only one I found is too technical for me to understand.

  1. In the following code, the thread and non-thread functions have different output. Why is that?

     #include <boost/thread.hpp> #include <iostream> #include <stdio.h> using namespace std; void fTry1(const char&); void fTry2(const char&); int main() { boost::thread tTry1, tTry2; const char *a = "efgh"; tTry1 = boost::thread(fTry1, *a); fTry2(*a); tTry1.join(); return 0; } void fTry1(const char& a) { cout << "Thread" << endl; cout << &a << endl; } void fTry2(const char& a) { cout << "Non-thread" << endl; cout << &a << endl; } 

Sample output:

Non-thread
efgh
Thread
e<garbage data>
  1. If I change the following line

     cout << &a << endl; 

    to

     cout << a << endl; 

The output becomes something like

Non-thread
e
Thread
e

Again, why?

--

The code I'm working on uses number 2 but the string being passed is a path to a folder, so I want the whole string, not just the first character. But since I don't understand how it works, I won't be able to make changes to it quite easily.

By default, the arguments passed to boost::thread will be "captured" by value . To capture them by reference , you have to use boost::ref ;

tTry1 = boost::thread(fTry1, boost::ref(*a));

This is pretty much like lambda functions, for example:

const char *a = "efgh";
const char &c = *a;

auto garbage = [c]() { // c captured by value
   cout << &c << endl;
};

auto works = [&c]() { // c captured by ref
    cout << &c;
};

garbage();
works();

Note:

Be careful passing references or pointers to a new thread, because you need to make sure they remain valid while the new thread is using it. In your unique case, however, that does not apply, because the string literal efgh has static duration so you are safe either way.

The string literal in const char *a = "efgh"; is compiled with a hidden terminator character '\\0' .

When you pass it like *a you're dereferencing it. You're basically passing only a character. This goes okay for the non threaded function, because if you use &a to take the address of the character a , making it a c-string, it will still point to the string literal "efgh" which includes the terminator. cout will keep printing until it hits the terminator.

But, I suspect, that when you pass *a to boost::thread it actually copies the character, but just the character, not the whole string. When you later turn it back into a c-style string using &a there is no more terminator character, so cout will just keep on printing on and on, and you see garbage.

When you change cout << &a << endl; to cout << a << endl; you're telling cout you only wnat to print 1 character. So it will only print 1.

You taged your question with c++ , why not use a std::string instead?

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