Thread: Constant Being Initialized AFTER Variable That Uses It

  1. #1
    Registered User
    Join Date
    Nov 2005
    Posts
    88

    Constant Being Initialized AFTER Variable That Uses It

    I am having a problem with a constant I am defining in MSVC++ 6.0.

    Basically, I declare a constant string exists in Test.h.

    extern const std::string strTest;

    In a cpp (other.cpp) file, I place the definition for strTest. It is marked as extern because without it, the constant would only be marked for internal linkage and results in a compiler error saying that strTest was never defined.

    extern const std::string strTest = "Test";

    In another cpp file (MyClass.cpp), I have a static member variable of a class. The declaration for the variable exists in MyClass.h. In MyClass.cpp I define the variable like so.

    std::string MyClass::strPath = strTest;

    However, when I run the code, strPath is filled with "" instead of "Test". I placed breakpoints on the strTest and strPath lines of code to see when each was occuring. I was suprised to find that the strPath line runs prior to the strTest line, and thus was initializing strPath with an uninitialized value of strTest. Is this expected behavior? I was under the impression that constants should be initialized before anything else.

    Is there anyway to solve this problem to ensure that every constant defined in such a way is initialized before any attempt is made to use it? Thank you for any input you have.

    Joe

  2. #2
    System Novice siavoshkc's Avatar
    Join Date
    Jan 2006
    Location
    Tehran
    Posts
    1,246
    You should place std::string strTest = "Test"; in global scope and extern std::string strTest; in your cpp. I am not sure if it can be a member of a class.
    Why you want to do this?
    Learn C++ (C++ Books, C Books, FAQ, Forum Search)
    Code painter latest version on sourceforge DOWNLOAD NOW!
    Download FSB Data Integrity Tester.
    Siavosh K C

  3. #3
    Registered User
    Join Date
    Nov 2005
    Posts
    88
    strTest is defined in a global scope. strPath is the member of the class. strTest is a constant and strPath is a regular variable.

    strTest is declared in Test.h, defined in other.cpp as shown in the lines of code above. strPath is declared as a static member variable in MyClass.h, and defined in MyClass.cpp as shown above.

    Thanks for your input. I hope that clarifies the issue.

  4. #4
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Place the extern declaration also in MyClass.h, before the class definition.

    const variables are visible only to the file in which they are declared. That is why your class is not seeing it.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  5. #5
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by mercury529
    strTest is defined in a global scope. strPath is the member of the class. strTest is a constant and strPath is a regular variable.

    strTest is declared in Test.h, defined in other.cpp as shown in the lines of code above. strPath is declared as a static member variable in MyClass.h, and defined in MyClass.cpp as shown above.
    Like this?
    Code:
    // MyClass.h
    #ifndef MYCLASS_H
    #define MYCLASS_H
    
    #include <string>
    
    class MyClass
    {
    public:
          static std::string strPath;
    };
    
    extern const std::string strTest;
    
    #endif
    Code:
    // MyClass.cpp
    #include "MyClass.h"
    
    std::string MyClass::strPath = strTest;
    Code:
    // other.cpp
    #include "MyClass.h"
    
    const std::string strTest = "Test";
    Code:
    // main.cpp
    #include <iostream>
    #include "MyClass.h"
    
    int main()
    {
        MyClass object;
        std::cout << object.strPath << '\n';
        std::cin.get();
        return 0;
    }
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  6. #6
    Registered User
    Join Date
    Nov 2005
    Posts
    88
    It would be like this

    Code:
    // MyClass.h
    #ifndef MYCLASS_H
    #define MYCLASS_H
    
    #include <string>
    #include "Test.h"
    
    class MyClass
    {
    public:
          static std::string strPath;
    };
    #endif
    Code:
    // MyClass.cpp
    #include "MyClass.h"
    
    std::string MyClass::strPath = strTest;
    Code:
    // other.cpp
    
    extern const std::string strTest = "Test";
    Code:
    //Test.h
    extern const std::string strTest;
    Code:
    // main.cpp
    #include <iostream>
    #include "MyClass.h"
    
    int main()
    {
        MyClass object;
        std::cout << object.strPath << '\n';
        std::cin.get();
        return 0;
    }
    Edit: As you can tell from the example above Mario, I am including Test.h in MyClass.h, so strTest is known inside of MyClass.cpp where it is being assigned to strPath.
    Last edited by mercury529; 07-29-2006 at 11:38 AM.

  7. #7
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    That has to be some problem with VC++ 6.0. Probably is is documented somewhere.

    There is nothing wrong with your code. Main should output "test".
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  8. #8
    System Novice siavoshkc's Avatar
    Join Date
    Jan 2006
    Location
    Tehran
    Posts
    1,246
    Compiler problem? const make the variable filescope, in other.cpp, it is const. So it is filescope. Don't make externs const.
    [edit] extern keyword is not needed in other.cpp.
    Last edited by siavoshkc; 07-29-2006 at 01:03 PM.
    Learn C++ (C++ Books, C Books, FAQ, Forum Search)
    Code painter latest version on sourceforge DOWNLOAD NOW!
    Download FSB Data Integrity Tester.
    Siavosh K C

  9. #9
    Registered User
    Join Date
    Nov 2005
    Posts
    88
    Const is no longer file scope when you define it as an extern const. If it were file scope, the linker would throw an error that it was undefined.

    What is the alternative to making an extern const string? Defining the string in the header file results in multiple definitions. Prefacing it with static would work but also results in a lot more unnecessary variables floating in memory. Also, I favor any method that has the definition of the constants in the cpp file. I am trying to make it flexible in such a way that I can swap in .cpp files to work with different constants.

    Thanks for any advice you can give.

  10. #10
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Quote Originally Posted by siavoshkc
    Compiler problem? const make the variable filescope, in other.cpp, it is const. So it is filescope. Don't make externs const.
    [edit] extern keyword is not needed in other.cpp.
    The extern keyword in other.cpp is not needed alright. When a variable is defined as it was in other.cpp, the extern keyword can be ommited. However it is considered good practice. It helps remember this particular const is to be used in other files...

    And "don't make extern const"? You suggest the OP to not use a popular language feature?

    Quote Originally Posted by mercury529
    Const is no longer file scope when you define it as an extern const. If it were file scope, the linker would throw an error that it was undefined.
    This is true. However you still have to declare the const in those files you wish to use it. Or the const will not be visible.

    Quote Originally Posted by mercury529
    What is the alternative to making an extern const string? Defining the string in the header file results in multiple definitions. Prefacing it with static would work but also results in a lot more unnecessary variables floating in memory. Also, I favor any method that has the definition of the constants in the cpp file. I am trying to make it flexible in such a way that I can swap in .cpp files to work with different constants.
    Defining the const in a cpp file is what is bringing you problems in the first place. One possible way to override this behavior of VC++ 6.0 is perhaps define the const in the header file. Since this particular const of yours is initialized from a constant expression, it is itself a constant expression. You can, and probably should, define it in the header file.

    It is, of course possible do what you are doing already. I just now tested your code to be absolute sure it works. And the obvious result is it does. But since VC++ 6.0 is not recognizing correctly the extern keyword, I can only suggest you move the definition to your header file. I'm sorry.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  11. #11
    Registered User
    Join Date
    Nov 2005
    Posts
    88
    The extern keyword in other.cpp is not needed alright. When a variable is defined as it was in other.cpp, the extern keyword can be ommited. However it is considered good practice. It helps remember this particular const is to be used in other files...
    If you remove extern from the example code, you will get a linker error. Extern const in a cpp file is not a matter of good practice, as much as it is a necessity to be able to define a constant in a global way. The code simply does not work without it.

    If I move the definition to the header file, how do I eliminate the re-defintion issue that occurs (when the header file is included in multiple files). Is making the const static the only way to get rid of it? I believed the better practice was to only mark the const as extern and then define in it in a cpp file. Unforunately, it appears that the MSVC++ 6 compiler runs into the assignment issue I originally detailed when I handle it this way.

    Can anyone else reproduce this in MSVC++ 6.0? Does this code function correctly in Borland or G++? Could it have to do with an optimization setting? The issue I discovered was the const was getting assigned after the static variable. This just seems to go against what should occur.

    Thanks again.

  12. #12
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by mercury529
    Can anyone else reproduce this in MSVC++ 6.0? Does this code function correctly in Borland or G++? Could it have to do with an optimization setting? The issue I discovered was the const was getting assigned after the static variable. This just seems to go against what should occur.
    With a little addition,
    Code:
    // other.cpp
    #include <string>
    extern const std::string strTest = "Test";
    MSVC6: blank stare.
    g++: expected result "Test".
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  13. #13
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Quote Originally Posted by mercury529
    If you remove extern from the example code, you will get a linker error. Extern const in a cpp file is not a matter of good practice, as much as it is a necessity to be able to define a constant in a global way. The code simply does not work without it.
    You are absolutely right about this. My bad. Too sleepy I guess.

    Quote Originally Posted by mercury529
    If I move the definition to the header file, how do I eliminate the re-defintion issue that occurs (when the header file is included in multiple files)
    Well, you define it with internal linkage.

    Code:
    const std::string strTest = "Test";
    And, you do provide header guards.

    Quote Originally Posted by mercury529
    Is making the const static the only way to get rid of it? I believed the better practice was to only mark the const as extern and then define in it in a cpp file.
    It can be done so. As I said before, even with constants initialized from constant expressions. However C++ defaults const to have internal linkage. It feels natural to follow on this behavior. Also the compiler will be able to evaluate your const. With external linkage the compiler is left in the dark as to the actual value of the const.

    Quote Originally Posted by mercury529
    Unforunately, it appears that the MSVC++ 6 compiler runs into the assignment issue I originally detailed when I handle it this way.
    I did some searching for you (as you probably did too by now), but came empty handed. Maybe my search string choices were not the best. But this is an old, unsuported and non standards conformant compiler. Do you really need to use it?
    Last edited by Mario F.; 07-29-2006 at 04:00 PM.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  14. #14
    Registered User
    Join Date
    Nov 2005
    Posts
    88
    Dave, I did have the <string> included.

    Mario, yeah, you are right. I had multiple definitions lingering from incomplete removal from the other locations.

    Are we agreed the behavior in MSVC++ 6 is incorrect for the code I wrote? I dislike having to put my definitions directly in the header file, but it looks as though I may have no choice. Unforunately I am stuck with MSVC++ 6 because it is the only legal version I own.

    Thanks for all the input.

    Joe

  15. #15
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by mercury529
    Unforunately I am stuck with MSVC++ 6 because it is the only legal version I own.
    Why not "buy" gcc?
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Creating a sysctl variable ?
    By taupin in forum C Programming
    Replies: 4
    Last Post: 06-28-2008, 05:21 PM
  2. Replies: 12
    Last Post: 05-28-2008, 04:10 AM
  3. Need some help...
    By darkconvoy in forum C Programming
    Replies: 32
    Last Post: 04-29-2008, 03:33 PM
  4. static class variable vs. global variable
    By nadamson6 in forum C++ Programming
    Replies: 18
    Last Post: 09-30-2005, 03:31 PM
  5. Replies: 2
    Last Post: 04-12-2004, 01:37 AM