1

I have a class which parses the Command line arguments and then returns the parsed value to the client class. For parsing, I need to pass argv to parse function. I would like to pass by reference but from what I know , we never use the '&' symbol when passing arrays. Arrays are not objects that can be passed by reference. Here is my code:

#include <iostream>
#include <fstream> 
using namespace std;

class cmdline
{
    const char * ifile;
    public:

    cmdline():ifile(NULL){}

    const char  * const getFile() const
    {
        return (ifile);
    }

    void parse(int argc,const  char** argv)
    {
        //parse and assign value to ifile 
        //  ifile = optarg;
        // optarg is value got from long_getopt

    }
};

int main(int argc, char ** argv)
{
    cmdline CmdLineObj;
    CmdLineObj.parse(argc, const_cast<const char**>(argv));
    const char * const ifile = CmdLineObj.getFile();
    ifstream myfile (ifile);
    return 0;
}

1) Is the way argv is treated, correct?

2) Better way to handle, ifile?

3) I want to return ifile as reference, what change should I do, if needed?

My code works the way it is supposed to work, but the reason I came to SO is to "not-just-make-it-work" but do it properly.

Thanks for your help.

EDIT:: After Mehrdad's comment, I edited like this:

class CmdLine
{
    const char *  ifile;

public:
    const  char  * & getFile() const
    {
        return (ifile);
    }

But I get the error - invalid initialization of reference of type ‘const char*&’ from expression of type ‘const char’

Ian McGrath
  • 982
  • 2
  • 10
  • 23
  • 3
    What do you mean by "My code works the way it is supposed to work"? This code does not even compile. – Mankarse Sep 18 '11 at 04:49
  • @Mankrase, I have edited the code. It compiles fine now. Thanks for pointing it out. Do you see anything wrong with this code (I mean some undefined behavior or something I should definitely take care of? I really want to return ifile by reference) – Ian McGrath Sep 18 '11 at 04:58
  • @Ian: `const char * const getFile() const` makes no sense. What is the second `const` supposed to do? – user541686 Sep 18 '11 at 05:00
  • @Mehrdad , Shouldn't it mean const pointer to a const char *? I can remove it if not needed.Thanks for your input. Any idea how can I return ifile as reference? – Ian McGrath Sep 18 '11 at 05:03
  • @Ian: Returning a "const pointer" to something makes no sense, because it behaves no differently from a pointer that *isn't* 'const' (since it's the return type of a method, and you can't normally assign to a return value). As for returning ifile by reference: Why don't you just return `const char *&`? – user541686 Sep 18 '11 at 05:05
  • @Mehrdad, Thanks. I edited the code as you said but I face just one error (more details in the edited question). How to fix this? I have to say reference and const are not my strong points. :( – Ian McGrath Sep 18 '11 at 05:14
  • Why do you want to return the pointer by reference? What useful operations will that allow? – Mankarse Sep 18 '11 at 05:18
  • @Ian: It's because `getFile` is `const`, so it means that it can *only* access `const` members of the class. So `ifile` is looks like a `const` variable, and so you can't return it by a mutable reference. If you want to return it as a *const* reference (I have no idea why you would want to, since you might as well return it by value), you need to say `const char *const &`. But then I have to ask: Why do you need to return it by reference in the first place? – user541686 Sep 18 '11 at 05:20
  • @Mankarse, Please correct me if I am wrong, but isn't returning by reference preferred over returning by value? That is the only reason I want to return by reference. – Ian McGrath Sep 18 '11 at 05:22
  • @Mehrdad, got it working. But before I ask any more questions, I think it is better I study references and consts one more time. Thank you very much for your time and help. I appreciate it very much. What about my comment about array not being able to pass as reference? Is that correct? – Ian McGrath Sep 18 '11 at 05:26
  • @Ian: that rule of thumb doesn't really apply to POD, but to complex data types for which the cost of copying is significant. Even then you can't blindly assume "return by reference is better", you need to consider the context. In this case there's no advantage to using return by reference versus return by value, because you're only talking about a single pointer. On the other hand, there's some good reasons _not to_ return by reference here, not the least of which being that it would be very atypical to do so with a pointer. – Eric Melski Sep 18 '11 at 05:26
  • @Ian McGrath - A reference is preferred (in some cases) if you are returning a large object, for performance reasons. In this case you are returning a pointer, which is already small enough to be returned in a register, so returning a reference instead just leads to needless confusion and runtime overhead. – Mankarse Sep 18 '11 at 05:27
  • @Eric, gotcha! Time to study the reference section of my C++ book once again. Thank you. What about array and reference comment? Is that correct? Argv is handled properly I suppose? – Ian McGrath Sep 18 '11 at 05:28
  • @Mankarse, Got it :) Thanks for your help and time. What about char [][] (argv), is that way ok? – Ian McGrath Sep 18 '11 at 05:29
  • You can pass an array by reference. You use the syntax: `Type (&arrayName)[size]`, where `Type` and `size` are replaced with the actual type of the array elements and size of the array respectively. – Mankarse Sep 18 '11 at 05:29
  • @Mankarse , what size do you recommend for argv? Is there any significant advantage passing argv as reference? – Ian McGrath Sep 18 '11 at 05:31
  • I cannot recommend a size for `argv`, because it does not have a size that is known at compile time. This means that there is no real way to pass it by reference. For other arrays this technique can be [useful](http://www.boost.org/doc/libs/1_47_0/doc/html/foreach.html) however. – Mankarse Sep 18 '11 at 05:37

1 Answers1

0

Arrays are not objects that can be passed by reference.

What makes you think that?

1) Is the way argv is treated, correct?

CmdLineObj.parse(argc, const_cast< const char** >(argv));

Why are you const casting that? Instead of casting, you could change your definition of main to const char** argv.

2) Better way to handle, ifile?

Well, there is always std::string, but since all you seem to do is then pass the value to an std::ifstream I don't see a point in using it.

3) I want to return ifile as reference, what change should I do, if needed?

What would be the point of returning a pointer as a reference? Are you expecting callers of getFile to actually change the member that points to such string? You shouldn't be doing that since getFile is a const member function. If you are thinking performance, then returning a reference to a pointer in this case will actually be worse than returning the pointer by value. The string contents are not getting copied when returned from getFile, like they would if ifile was instead an std::string (in which case returning a const reference would make sense).

K-ballo
  • 80,396
  • 20
  • 159
  • 169
  • No, that conversion would not be done implicitly by the compiler, because it is [unsafe](http://stackoverflow.com/questions/3496000/why-is-it-not-ok-to-pass-char-to-a-function-that-takes-a-const-char-in). – Mankarse Sep 18 '11 at 05:32
  • @K-ballo, I am perfect example of little knowledge is dangerous. What should I do about passing argv as reference? If it serves any benefit? – Ian McGrath Sep 18 '11 at 05:35
  • @Mankarse: You are right, I will edit the question accordingly. – K-ballo Sep 18 '11 at 05:36
  • @Ian McGrath: Generally speaking, there is no gain in passing a pointer as reference **unless** you expect the callee to change the address to where it points. – K-ballo Sep 18 '11 at 05:37
  • @K-ballo, so my handling of argv is ok? I will only use argv for parsing and nothing else. No change of address at any point. – Ian McGrath Sep 18 '11 at 05:42
  • 1
    @K-ballo - Changing the definition of main would leave you with a non-standard-conforming program however. The only two required signatures for main are `int main()` and `int main(int argc, char argv[])`. That said, I do not know of any compiler that would not allow `int main(int argc, char const argv[])`. – Mankarse Sep 18 '11 at 05:43
  • @Ian McGrath: Yes, passing it as a pointer is ok. I would redeclare `main` so that `argv` is a `const char**` to begin with, though. – K-ballo Sep 18 '11 at 05:45
  • @Mankarse: My interpretation of the standard is that while those two signatures must be supported, its actual type its implementation defined. Other definitions can be provided and the standard even mentions adding further parameters. However there is still point in what you mention, +1 for that. – K-ballo Sep 18 '11 at 05:48
  • 1
    @K-ballo, you are correct - the standard explicitly mentions the possibility of implementation defined signatures for main, but if you want to be able to have your program be guaranteed to work on **any** conforming implementation, then you cannot rely on such things. I personally think that the const correctness gains are probably enough to justify using a non-standard main, but it is still worth noting. – Mankarse Sep 18 '11 at 05:52