7

我只是想使用 Visual Studio 2012 Release Candidate C++ 编译一个更大的项目。该项目现在使用 VS2010 编译。(我只是贪婪地获得 C++11 的东西,所以我尝试了。:)

除了我可以自己解释的事情之外,该项目使用如下代码:

ostringstream ostr;
ostr << "The " __FUNCTION__ "() failed to malloc(" << i << ").";
throw bad_alloc(ostr.str().c_str());

编译器现在抱怨

error C2248: 'std::bad_alloc::bad_alloc' : cannot access private member declared 
    in class 'std::bad_alloc'

......这是真的。该版本的构造函数现在是私有的。

将该版本的构造函数设为私有的原因是什么?C ++ 11标准是否建议不要将该构造函数与参数一起使用?

(我可以想象,如果分配失败,尝试构建新的东西可能会导致更多问题。但是,这只是我的猜测。)

谢谢,彼得

4

2 回答 2

14

C++11 标准bad_alloc是这样定义的(18.6.2.1):

class bad_alloc : public exception {
public:
    bad_alloc() noexcept;
    bad_alloc(const bad_alloc&) noexcept;
    bad_alloc& operator=(const bad_alloc&) noexcept;
    virtual const char* what() const noexcept;
};

没有带字符串的构造函数。提供这种构造函数的供应商会使使用它的代码不可移植,因为其他供应商没有义务提供它。

C++03 标准定义了一组类似的构造函数,所以 VS 甚至在 C++11 之前就没有遵循这部分标准。MS 确实试图使 VS 尽可能地符合标准,所以他们可能只是利用这个场合(新的 VS,新的标准)来修复不兼容的问题。

编辑:现在我已经看到了 VS2012 的代码,也很清楚为什么提到的构造函数是私有的,而不是被完全删除:在类中似乎只有一个构造函数的使用bad_array_new_length。所以在 bad_allocbad_array_new_length中声明为 a friend,因此可以使用该私有构造函数。bad_array_new_length如果只是将消息存储在 by 使用的指针中,则可以避免这种依赖关系what(),但无论如何它并不是很多代码。

于 2012-06-27T20:23:50.457 回答
1

如果您习惯于在抛出 std::bad_alloc 时传递消息,则一种合适的技术是定义一个派生自 std::bad_alloc 的内部类,并覆盖“what”以提供适当的消息。

您可以将类公开并直接调用赋值构造函数,或者制作一个辅助函数,例如 throw_bad_alloc,它接受参数(和附加标量信息)并将它们存储在内部类中。

在调用“what”之前,该消息不会被格式化。这样,堆栈展开可能已经释放了一些内存,因此可以在捕获站点使用实际原因(内存耗尽、错误请求大小、堆损坏等)格式化消息。如果格式化失败,只需分配并返回静态消息。

修剪示例:

(提示:复制构造函数可以将 _Message 分配给 nullptr,而不是复制消息,因为消息是按需格式化的。移动构造函数当然可以没收它:-)。

class internal_bad_alloc: public std::bad_alloc
   {
   public:
      // Default, copy and move constructors....

      // Assignment constructor...
      explicit internal_bad_alloc(int errno, size_t size, etc...) noexcept:
         std::bad_alloc()
         {
         // Assign data members...
         }

      virtual ~internal_bad_alloc(void) noexcept
         {
         // Free _Message data member (if allocated).
         }

      // Override to format and return the reason:
      virtual const char* what(void) const noexcept
         {
         if (_Message == nullptr)
            {
            // Format and assign _Message.  Assign the default if the
            // format fails...
            }
         return _Message;
         }

   private:
      // Additional scalar data (error code, size, etc.) pass into the
      // constructor and used when the message is formatted by 'what'...
      mutable char* _Message;
      static  char  _Default[];
   }
};

//
// Throw helper(s)...
//
extern void throw_bad_alloc(int errno, size_t size, etc...)
   {
   throw internal_bad_alloc(errno, size, etc...);
   }
于 2013-05-10T18:19:45.643 回答