为什么它可以在GNU/C++中编译,而不能在VC++2010 RTM中编译?

发布于 2024-08-27 11:45:02 字数 2995 浏览 7 评论 0原文

#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-vistaspecial r3)) 中,有两个编译错误:

描述资源路径位置类型 从 std::auto_ptr<_Tp>::operator std::auto_ptr<_Tp1>() 的结果初始化 void sink_base(std::auto_ptr)' 的参数 1 [with _Tp1 = Base , _Tp = 派生]' 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想要解决?”

#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;
}

In Eclipse(GNU C++.exe -v gcc version 3.4.5 (mingw-vista special r3)) it's two compile error:

Description Resource Path Location Type
initializing argument 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++ Problem

Description Resource Path Location Type
no matching function for call to `std::auto_ptr::auto_ptr(std::auto_ptr)' auto_ptr_ref_research.cpp auto_ptr_ref_research/auto_ptr_ref_research 190 C/C++ Problem

But it's right in VS2010 RTM.

Questions:

  1. Which compiler stand for the ISO C++ standard?

  2. The content of case 4 is the problem "auto_ptr & auto_ptr_ref want to resolve?"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

还给你自由 2024-09-03 11:45:02

我认为缩短的版本是:

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_ptr 替换为 unique_ptr,并将接收器函数的签名更改为使用右值,则可以工作参考资料以获得所有权转让。

void sink_base( std::unique_ptr<Base>&& p);

I think a shortened version is:

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

X make() { return X(); }

void receive(X ) { }

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

Note the unusual form of copy constructor (from a non-const reference) which prevents (by standard, GCC is correct) the ability to copy-construct an instance from a temporary (the result of make()).


The situation is way more complicated because std::auto_ptr attempts to work around with the resulting limitations with a wrapper auto_ptr_ref. However, since you also want to change the type of the pointer, it probably breaks down somewhere with all those implicit conversions and VC++ manages to compile it only thanks to a nonstandard extension (allowing binding rvalues to non-constant references).

The compiler actually tells me right that. On the problem line:

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

Anyway, std::auto_ptr is a bit of a failed experiment with bizarre semantics, and deprecated in the next standard. In C++0x (e.g with gcc 4.4.1) it would work if you replaced all occurrences of auto_ptr with unique_ptr, and changed the signature of sink functions to use rvalue references to get the ownership transferring.

void sink_base( std::unique_ptr<Base>&& p);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文