1
#include <stdlib.h>
#include <iostream>
#include <memory>
#include "copy_of_auto_ptr.h"
#ifdef _MSC_VER
#pragma message("#include <string>")
#include <string>
// http://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html#Diagnostic-Pragmas
#endif

/*
 case 1-4 is the requirement of the auto_ptr.
 which form http://ptgmedia.pearsoncmg.com/images/020163371X/autoptrupdate/auto_ptr_update.html
*/
/*
 case 1.
 (1) Direct-initialization, same type, e.g.
*/
std::auto_ptr<int> source_int() {
    // return std::auto_ptr<int>(new int(3));
    std::auto_ptr<int> tmp(new int(3));
    return tmp;
}

/*
 case 2.
 (2) Copy-initialization, same type, e.g.
*/
void sink_int(std::auto_ptr<int> p) {
    std::cout << "sink_int << " << *p << std::endl;
}

/*
 case 3.
 (3) Direct-initialization, base-from-derived, e.g.
*/

class Base {
public:
    Base() {
        std::cout << "creating Base object..." << std::endl;
    }
    virtual ~Base(){
        std::cout << "destoring Base object..." << std::endl;
    }
    virtual void go(){
        std::cout << "Base::go()" << std::endl;
    }
};

class Derived : public Base {
public:
    Derived() {
        std::cout << "creating Derived object..." << std::endl;
    }
    ~Derived(){
        std::cout << "destoring Derived object..." << std::endl;
    }
    void go(){
        std::cout << "Derived::go()" << std::endl;
    }
};

std::auto_ptr<Derived> source_derived() {
    // return std::auto_ptr<Derived>(new Derived());
    std::auto_ptr<Derived> tmp(new Derived());
    return tmp;
}

/*
 case 4.
 (4) Copy-initialization, base-from-derived, e.g.
*/
void sink_base( std::auto_ptr<Base> p) {
    p->go();
}

int main(void)
{
    /*
    // auto_ptr
    */
    // case 1. // auto_ptr
    std::auto_ptr<int> p_int(source_int());
    std::cout << *p_int << std::endl;

    // case 2. // auto_ptr
    sink_int(source_int());

    // case 3. // auto_ptr
    std::auto_ptr<Base> p_derived(source_derived());
    p_derived->go();

    // case 4. // auto_ptr
    sink_base(source_derived());

    return 0;
}

Eclipse (GNU C++.exe -v gcc version 3.4.5 (mingw-vista special r3)) では、次の 2 つのコンパイル エラーが発生します。

説明 リソース パス 場所 タイプ 初期化引数 1 of void sink_base(std::auto_ptr<Base>)' from result ofstd::auto_ptr<_Tp>::operator std::auto_ptr<_Tp1>() [with _Tp1 = Base, _Tp = Derived]' auto_ptr_ref_research.cpp auto_ptr_ref_research/auto_ptr_ref_research 190 C/C++ 問題

説明 リソース パスの場所 タイプ `std::auto_ptr::auto_ptr(std::auto_ptr)' の呼び出しに一致する関数はありません auto_ptr_ref_research.cpp auto_ptr_ref_research/auto_ptr_ref_research 190 C/C++ の問題

しかし、VS2010 RTM では正しいです。

質問:

  1. ISO C++ 標準を表すコンパイラはどれですか?

  2. ケース 4 の内容は、「auto_ptr & auto_ptr_ref を解決したいですか?」という問題です。

4

1 に答える 1

7

短縮版は次のとおりです。

struct X
{
    X() {}
    X(X&);
};

X make() { return X(); }

void receive(X ) { }

int main()
{
    receive(make());
}

一時的な(の結果)からインスタンスをコピー構築する機能を(標準ではGCCが正しい)妨げる、(非定数参照からの)コピーコンストラクターの異常な形式に注意してくださいmake()


std::auto_ptr結果として生じる制限をラッパーで回避しようとするため、状況ははるかに複雑になりますauto_ptr_ref。ただし、ポインタのタイプも変更したいので、おそらくこれらすべての暗黙の変換でどこかで壊れ、VC ++は非標準の拡張機能(非標準の参照への右辺値のバインドを許可)のおかげでのみそれをコンパイルできます。

コンパイラは実際にそれを正しく教えてくれます。問題のある行:

warning C4239: nonstandard extension used : 'argument' : 
conversion from 'std::auto_ptr<_Ty>' to 'std::auto_ptr<_Ty> &' 

とにかく、std::auto_ptr奇妙なセマンティクスで少し失敗した実験であり、次の標準で非推奨になりました。C ++ 0x(gcc 4.4.1など)では、のすべての出現箇所をで置き換えauto_ptrunique_ptr所有権の譲渡を取得するために右辺値参照を使用するようにシンク関数のシグネチャを変更した場合に機能します。

void sink_base( std::unique_ptr<Base>&& p);
于 2010-04-06T18:00:53.420 に答える