3

I would like to have a static char array member initialized in terms of other static char array members - but the initialization is such that code is necessary. Is this possible?

class fred {
    static char *a;
    static char *b;
    static char c[4];
}

Now a and b will have fixed values, but I want to construct c in terms of them. EG:

fred::a = "1234"
fred::b = "ab"    
strcpy(c, b);
strncat(c, a, 1);

However I can't see anyway to initialize c, other than to make a class for the purpose which is just a char[4], with a constructor that references fred::a and fred::b, and then replace c in fred with an instance of that class - which is awkward when referencing the c char array.

Is there a better way?

bandjalong
  • 483
  • 2
  • 6
  • 9
  • Is there some really good reason why you can't use std::string here? – shuttle87 Jun 19 '12 at 01:38
  • I don't use string, because it will be accessed a lot, and I'm assuming (perhaps erroneously) that a naked char array with have better performance. – bandjalong Jun 19 '12 at 01:45
  • Just stating that should make it clear that's not how you should be doing things. – David Schwartz Jun 19 '12 at 01:58
  • 2
    @user1425406 Never ever base your performance-related decisions on assumptions, no matter how obvious you think they are. In general sense the compiler is better at generating high-performance code than you are, so just follow "good"/common practices whenever possible and only consider alternatives whenever you have *proven*(by a *benchmark*) that performance is an issue. Premature optimization is the .... You know the deal. :) – zxcdw Jun 19 '12 at 02:08
  • @DavidSchwartz - can you please explain? What part of what I'm doing do you think I'm not doing correctly? Using a char array rather than a string? – bandjalong Jun 19 '12 at 02:09
  • @zxcdw : It's not really premature optimization, I come from a long C background, so char arrays are what I use automatically. But if there is any difference at all in the access time between the char array and strings then I probably want the char array. The accesses will be in loops with trillions of iterations, and consequently every nanosecond matters! – bandjalong Jun 19 '12 at 02:14
  • @user1425406 Oh but it is because you are assuming that access times for std::string are different even if you know you'll have performance-critical code. That's not something you tested: you assumed it. I think you'll be pleasantly surprised if you test the two. Of course std::string does incur a heap allocation overhead for creating the string, but if by access you mean read-only access... well, best that you try it for yourself so you can get over this initial reluctance. Distrust is one of the key causes of premature optimization. The point zxcdw was making was precisely this. – stinky472 Jun 19 '12 at 02:31
  • @user1425406 but also to note is that structure can aid optimization. You say you'll be accessing strings over trillions of iterations in tight loops where every nanosecond matters. Well, are you doing string comparison? Why not just do integral comparison? If you map strings to a table, you can store associated integrals and compare them rather than the actual contents of the string. Tada: serious optimization. But that's going to be hard to swap out code if you have your code littered with strcmps rather than dependencies to a string interface such as the one that std::string provides. – stinky472 Jun 19 '12 at 02:39
  • I've actually got to use the string for pattern matching allowing for some mismatches and in the futures possibly indels as well. I have done the serious optimizations (approaching 2 orders of magnitude speed up by now). I agree that I would need to benchmark to prove that char arrays are better, but that would take me time no? And I'm still a bit unfamiliar with strings. These being static, the size doesn't matter, and if the extra layer of indirection associated with string is optimized away they that would be fine. But I wouldn't really gain anything from the change I think.. – bandjalong Jun 19 '12 at 02:47

3 Answers3

4

Edit: Originally, I had wilma as a friend of fred, and a static instance of wilma doing the initialization. I have changed the example to have dino declared within fred since the OP said he thought that would be cleaner.

You can create a static instance of a class inside fred whose job is to initialize c for you.

class fred {
    static char *a;
    static char *b;
    static char c[4];
    static struct dino { dino (); } dino_flintstone;
};

char *fred::a;
char *fred::b;
char fred::c[4];
fred::dino fred::dino_flintstone;

fred::dino::dino () {
    fred::a = "1234";
    fred::b = "ab";
    strcpy(fred::c, fred::b);
    strncat(fred::c, fred::a, 1);
}
jxh
  • 69,070
  • 8
  • 110
  • 193
  • I tried this, and it looks like it works, thanks! I don't quite understand what you mean by calling the class something else if I want to define wilma inside fred (which would indeed be a bit neater). – bandjalong Jun 19 '12 at 02:00
  • @user1425406: Terrific, yabba dabba doo! +1 on your question from me. – jxh Jun 19 '12 at 02:04
  • @user1425406 He means it just as a joke. There's no real reason or need to rename it if it's a class member. :) – zxcdw Jun 19 '12 at 02:04
  • @user1425406: I modified the example to have `dino` inside of `fred`. Regards – jxh Jun 19 '12 at 02:29
  • 1
    Hmm, Fred inside Wilma, Dino inside Fred. Double entendre if I ever saw one. – Cloud Jun 19 '12 at 02:37
  • Sorry, my sense of humour needed rebooting. But yes, I like the internal solution better. Although I'd like it better still if C++ actually supported this in a natural way! – bandjalong Jun 19 '12 at 02:38
  • Good sense of humor! it's nice to get out from seriousness :) – Edgar Villegas Alvarado Jun 19 '12 at 02:59
  • @user1425406: Ah, that's the blessing and curse that is C++. There's always a better way. I know I'm still always looking for it. Never give up, never surrender! Regards – jxh Jun 19 '12 at 03:07
1

Consequtive string literals are concatenated at compile-time...

#define A "1234"
#define B "ab"
fred::a = A;
fred::b = B;    
fred::c = A B;
Andrew Tomazos
  • 66,139
  • 40
  • 186
  • 319
  • Doesn't quite work because `c` becomes `{ 'a', 'b', '1', '2' }` instead of `"ab1"`. – jxh Jun 19 '12 at 01:45
1

You can't in a clean way, but you can use a trick to simulate an static constructor as shown here.

In that static constructor, you can initialize c. This would be a possible implementation:

class fred {
    static char *a = "1234";
    static char *b = "ab";
    static char c[4];
    public:
    fred(){
       strcpy(fred::c, fred::b);
       strncat(fred::c, fred::a, 1);
    }    
}

class Fred_staticInitializer{  
    static fred staticInitializer;  //This does the trick (launches constructor)
}

Hope it helps. Cheers

Community
  • 1
  • 1
Edgar Villegas Alvarado
  • 18,204
  • 2
  • 42
  • 61
  • This is a good trick if `fred` is never instantiated by anyone else. It should probably have at least a check to see if it is already initialized. – jxh Jun 19 '12 at 01:54
  • I think the asker can do that with this guideline. But you're totally right – Edgar Villegas Alvarado Jun 19 '12 at 01:59
  • I don't quite understand, won't the fred constructor be called everytime I create a fred instance? This would not be desirable.. – bandjalong Jun 19 '12 at 02:04