Re: Saving a binary file into a string

Discussion in 'C++' started by Jorgen Grahn, Dec 27, 2009.

  1. Jorgen Grahn

    Jorgen Grahn Guest

    On Sun, 2009-12-27, Dominik Schmidt wrote:
    > Hi,
    >
    > I'm new to C++, so I have a very basic question.
    > I wrote a function which opens a file and saves it into a string variable.
    > Another function can save a string variable into a file.


    ....
    > void SaveFile(string FilePath, string FileContent)


    You should learn to use references; that's better written as

    void SaveFile(const string& path, const string& s)

    Having to fit the whole file in memory *once* is problematic enough;
    here you double the memory needed.

    You also almost always need a way to report errors.

    > {
    > ofstream file1;
    > long long filesize;
    > char Chr1;
    >
    > filesize = FileContent.length();
    >
    > if (FileExists(FilePath)) KillFile(FilePath);
    > if (FileExists(FilePath)) return;


    Don't ask for permission; just try to do it (truncating the existing
    file as you go). You ask the wrong question anyway -- you might just
    as well fail because you don't have write permissions, or the disk is
    almost full, or ...

    The checks are also leaky because the thing you try to check for and
    make sure is true, can become false a microsecond later, when some
    other process creates that file.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
    Jorgen Grahn, Dec 27, 2009
    #1
    1. Advertising

  2. Jorgen Grahn

    Kaz Kylheku Guest

    On 2009-12-27, Jorgen Grahn <> wrote:
    > On Sun, 2009-12-27, Dominik Schmidt wrote:
    >> Hi,
    >>
    >> I'm new to C++, so I have a very basic question.
    >> I wrote a function which opens a file and saves it into a string variable.
    >> Another function can save a string variable into a file.

    >
    > ...
    >> void SaveFile(string FilePath, string FileContent)

    >
    > You should learn to use references; that's better written as
    >
    > void SaveFile(const string& path, const string& s)


    Under any sanely implemented compiler, there is no difference.

    So this is like writing x >> 2 instead of x / 2.

    The caller passes pointers to the objects; the callee will make copy
    if it modifies the arguments, otherwise it works with the caller's
    objects directly.

    > Having to fit the whole file in memory *once* is problematic enough;
    > here you double the memory needed.


    Even if the compiler is stupid to actually copy the objects in argument
    passing, the implementation of std::string can prevent copying the
    actual data by managing references.
    Kaz Kylheku, Dec 28, 2009
    #2
    1. Advertising

  3. On Dec 28, 1:07 am, Kaz Kylheku <> wrote:
    > void SaveFile(string FilePath, string FileContent)
    > void SaveFile(const string& path, const string& s)
    >
    > Under any sanely implemented compiler, there is no difference.
    >
    > So this is like writing x >> 2 instead of x / 2.
    >
    > The caller passes pointers to the objects; the callee will make copy
    > if it modifies the arguments, otherwise it works with the caller's
    > objects directly.


    Really? This surprises me, considering this is the first I've heard
    about such magics, and many longtime posters here seem to assume /
    know otherwise. Division by two vs bitshifting is very simply,
    provably equivalent code, but changing a pass by value to a pass by
    const ref is much more involved, and I believe the analogy does not
    work.

    So, how would this be implemented and still have a separate
    compilation model?

    Ex:

    //
    #include <iostream>
    using namespace std;

    class foo
    {
    public:
    foo() { cout << "foo()" << endl; }
    foo(const foo& ) { cout << "foo(const foo& )" << endl; }
    foo& operator= (const foo& ) { cout << "foo& operator= (const foo& )"
    << endl; return *this; }
    ~foo() { cout << "~foo()" << endl; }
    };

    void passByValue(foo ) {}

    int main()
    {
    foo x;
    passByValue(x);
    }
    //

    I think that this example must have exactly one ctor call, one copy
    ctor call, and 2 dtor calls. I don't see how you can change it and
    still have it be standard compliant.

    On a more general program, barring whole program optimization with the
    standard's "as if" rule, that is still with separate compilation, I
    don't see how you can do it.

    > Even if the compiler is stupid to actually copy the objects in argument
    > passing, the implementation of std::string can prevent copying the
    > actual data by managing references.


    Except it might not do copy on write strings because that can be more
    expensive for certain applications. That's a tradeoff optimization,
    not a globally better one.
    Joshua Maurice, Dec 28, 2009
    #3
  4. Jorgen Grahn

    James Kanze Guest

    On Dec 28, 6:07 am, Kaz Kylheku <> wrote:
    > On 2009-12-27, Jorgen Grahn <> wrote:


    [...]
    > >> void SaveFile(string FilePath, string FileContent)


    > > You should learn to use references; that's better written as


    > > void SaveFile(const string& path, const string& s)


    > Under any sanely implemented compiler, there is no difference.


    So g++, VC++ and Sun CC aren't sanely implemented. (Avoiding
    the copy is very tricky, since the legality of the optimization
    cannot be determined until link time.)

    --
    James Kanze
    James Kanze, Dec 28, 2009
    #4
  5. Jorgen Grahn

    Kaz Kylheku Guest

    On 2009-12-28, Joshua Maurice <> wrote:
    > On Dec 28, 1:07 am, Kaz Kylheku <> wrote:
    >> void SaveFile(string FilePath, string FileContent)
    >> void SaveFile(const string& path, const string& s)
    >>
    >> Under any sanely implemented compiler, there is no difference.
    >>
    >> So this is like writing x >> 2 instead of x / 2.


    Of course, that should have been x >> 1; sorry.

    >> The caller passes pointers to the objects; the callee will make copy
    >> if it modifies the arguments, otherwise it works with the caller's
    >> objects directly.

    >
    > Really? This surprises me, considering this is the first I've heard
    > about such magics, and many longtime posters here seem to assume /
    > know otherwise.


    Re-reading paragraph 15 of 12.8 of ISO/IEC 14882-2003, I'm not so sure any
    more.

    It's quite certain that copy construction can be elided when a class value is
    returned, but it's not so clear that the optimization is allowed in parameter
    passing, except when a temporary is involved.

    That is to say, if we have a function void f(string s); and we call it such
    that the parameter is initialized with a temporary object, for instance:

    f(string("abc"))

    the copying of the temporary can be elided; the parameter is simply
    constructed from "abc". Argument passing of non-temporaries does not meet the
    listed criteria for elision. I.e. it really is the case that the C++
    programmer must manually arrange this by using the const reference syntax.

    The optimization can only be done for classes with implicitly declared copy
    constructors and destructors, in keeping with the as-if principle.
    Kaz Kylheku, Dec 29, 2009
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Luis Esteban Valencia
    Replies:
    0
    Views:
    2,497
    Luis Esteban Valencia
    Jan 6, 2005
  2. G-Factor

    Saving a binary file help.

    G-Factor, Jul 7, 2003, in forum: C++
    Replies:
    7
    Views:
    434
    Thomas Matthews
    Jul 7, 2003
  3. Rune Allnor
    Replies:
    3
    Views:
    364
    Richard Herring
    Jan 15, 2010
  4. Jonathan Lee
    Replies:
    1
    Views:
    357
    Jonathan Lee
    Dec 27, 2009
  5. Kaz Kylheku
    Replies:
    1
    Views:
    374
    Fred Zwarts
    Dec 28, 2009
Loading...

Share This Page