简体   繁体   English

我应该使用std :: size_t来计算类的实例吗?

[英]Should I use std::size_t to count instance of my class?

I have a class: 我有一堂课:

class Nothing
{

    /// Constructor, Destructor, Copy and Assignment
    public:
    Nothing();
    ~Nothing();
    Nothing(const Nothing& clone);

    /// Operators
    const Nothing& operator=(const Nothing& other);

    /// Static Members
    private:
    static unsigned long long id_counter;
    static unsigned long long instance_counter;
};


Nothing::Nothing()
{
    m_name.clear();
    id_counter ++;
    m_id = id_counter;

    instance_counter ++;
}

Nothing::~Nothing()
{
    m_name.clear();
    instance_counter --;
}

Nothing::Nothing(const Nothing& other)
{

}

unsigned long long Nothing::id_counter = 0;
unsigned long long Nothing::instance_counter = 0;

Notice I am using unsigned long long to count instances of the class. 注意,我正在使用unsigned long long来计数该类的实例。 Should I use std::size_t instead? 我应该改用std :: size_t吗?

As an aside: If I have an instance of a class, and I do something like this: 顺便说一句:如果我有一个类的实例,并且我做这样的事情:

Nothing instance;
instance(Nothing()); // Calling copy constructor

Will the destructor be called before the copy constructor is called? 会在调用复制构造函数之前先调用析构函数吗? Reason for asking is do I need id_counter ++; 问原因是我需要id_counter ++;id_counter ++; and instance_counter ++; instance_counter ++; inside of my copy constructor? 在我的复制构造函数中?

std::size_t definition is implementation specific, as you can see in en.cppreference . std :: size_t定义是特定于实现的,如您在en.cppreference所见 In most implementations you will find it is defined as unsigned int . 在大多数实现中,您会发现它被定义为unsigned int

So to answer your question, you can use it instead of unsigned long long if you prefer, and your code will remain portable (as long as you don't actually require it to be 64-bit long) in the sense that std::size_t is guaranteed to be defined on every c++ compiler. 因此,要回答您的问题,可以根据需要使用它,而不用unsigned long long ,并且您的代码将保持可移植性(只要您实际上并不要求它的64位长即可),其含义为std ::保证在每个c ++编译器上都定义size_t。 If the unsigned long long requirement is a mandatory (which I doubt since you are using it for instance count) then its best to stick with unsigned long long . 如果unsigned long long要求是强制性的(我怀疑是因为您使用它来进行计数),那么最好坚持使用unsigned long long

 instance(Nothing); // Calling copy constructor: Should this be `instance(Nothing())`? 

This is bad syntax. 这是错误的语法。 If you are trying to invoke the copy ctor on a newly formed instance you should call Nothing copyInstance (Nothing()); 如果尝试在新形成的实例上调用copy ctor ,则应调用Nothing copyInstance (Nothing()); . Of course that's a very silly thing to do since you are copying a "clean" instance, you might as well have called Nothing copyInstance; 当然,这是一件很愚蠢的事情,因为您正在复制“干净”实例,因此您可能还调用了Nothing copyInstance; to the same effect. 达到同样的效果。

do I need id_counter ++; 我需要id_counter ++; and instance_counter ++; 和instance_counter ++; inside of my copy constructor? 在我的复制构造函数中?

You should definitely increment instance_counter since you are constructing a new instance. 您肯定应该增加instance_counter,因为您正在构建一个新实例。 You didn't specify what id_counter counts (reference count??) so it's hard to say. 您没有指定id_counter的计数(引用计数?),所以很难说。

Will the destructor be called before the copy constructor is called? 会在调用复制构造函数之前先调用析构函数吗?

Nowhere in your code do I see a place where the dtor will be called but since you are allocating instance on the stack, its destructor will be called once instance reaches the end of its scope (next } appearance). 无处在你的代码,我看到一个地方的dtor会被调用,但因为你是分配instance在栈上,一旦它的析构函数将被称为instance达到其范围(下一结束}外观)。

std::size_t is the type of a sizeof expression and usually the type returned by size() and capacity() of the STL containers. std::size_tsizeof表达式的类型,通常是STL容器的size()capacity()返回的类型。 (Technically, the STL containers each typedef a size_type , but that's almost always equivalent to std::size_t .) (从技术上讲,STL容器每个typedef都定义一个size_type ,但这几乎总是等于std::size_t 。)

Except for machines with weird memory models (eg, one that distinguishes between "near" and "far" pointers), a std::size_t will always be large enough to count all of the objects that you can fit into memory at one time. 除了具有奇怪的内存模型的机器(例如,区分“近”和“远”指针的机器)外, std::size_t总是足够大,可以一次计数所有您可以放入内存的对象。 This is not a direct guarantee, but a side-effect of the way the definitions are written. 这不是直接保证,而是定义定义方式的副作用。

Therefore, std::size_t is a natural type for things like instance counts. 因此, std::size_t是实例计数之类的自然类型。

Note that std::size_t is an unsigned type. 请注意, std::size_t是无符号类型。 Many people believe you should avoid unsigned types except for representing actual bit patterns (for example, see the Google Style Guide ). 许多人认为您应该避免使用无符号类型,除了代表实际的位模式(例如,请参阅Google样式指南 )。 By using an unsigned type, some arithmetic operations may behave in surprising ways. 通过使用无符号类型,某些算术运算可能会以令人惊讶的方式表现。 If you had a bug that caused your instance count to go negative, it might be hard to detect, because a negative value will wrap around to a very large positive value. 如果您有一个导致实例计数变为负数的错误,则可能很难检测到,因为负数会回绕到非常大的正值。

Personally, I find that argument unpersuasive; 我个人认为这种说法没有说服力。 signed arithmetic also behaves in surprising ways when dealing with overflow and underflow. 在处理上溢和下溢时,有符号算术的表现也令人惊讶。 Also, when you're trying to use STL types, assigning size() to a signed value or comparing a signed value to size() requires explicit casts or disabling compiler warnings. 另外,当您尝试使用STL类型时,将size()分配给一个带符号的值或将一个带符号的值与size()进行比较都需要显式强制转换或禁用编译器警告。 I dislike disabling compiler warnings, especially since they can help you find many of the bugs that people fear when they suggest avoiding unsigned types. 我不喜欢禁用编译器警告,特别是因为它们可以帮助您发现人们建议避免使用无符号类型时会担心的许多错误。

I would used std::size_t . 我会用std::size_t There's nothing wrong with unsigned long long , but that might not scale as well with the host platform. unsigned long long没什么错,但是在主机平台上可能无法很好地扩展。

If you want to keep your options open, then you can add a typedef to your Nothing class, which makes it easy to change your mind later: 如果要保持选项打开,则可以在Nothing类中添加一个typedef,这样以后可以轻松更改主意:

/// Static Members
private:
typedef unsigned long long CounterType;  // consider std::size_t
static CounterType id_counter;
static CounterType instance_counter;

You could even call your typedef size_type if you want to match the style of the STL containers. 如果要匹配STL容器的样式,甚至可以调用typedef size_type

I am using unsigned long long to count instances of the class. 我正在使用unsigned long long来计算类的实例。 Should I use std::size_t instead? 我应该改用std :: size_t吗?

There's no reason to use std::size_t and no reason not to use std::size_t . 没有理由不使用std::size_t ,也没有理由不使用std::size_t It's a useful type for things like array indices (see: unsigned int vs. size_t ), but does not correlate at all to the maximum quantity of objects that you can create in any given program. 对于数组索引之类的东西,这是一种有用的类型(请参阅: unsigned int vs. size_t ),但与您可以在任何给定程序中创建的最大对象数量完全不相关。 So just choose whichever you like based upon how many objects you think you're going to have. 因此,只要选择任何你喜欢基于有多少个对象认为你有。

Will the destructor be called before the copy constructor is called? 会在调用复制构造函数之前先调用析构函数吗?

You didn't call the copy constructor at all. 您根本没有调用复制构造函数。 In fact you can never "call" any constructor. 实际上,您永远无法“调用”任何构造函数。 The copy constructor is automatically invoked when you create a new object and initialise it from an existing object, but nowhere in your code do you do that. 创建新对象并从现有对象对其进行初始化时,将自动调用副本构造函数,但是您在代码中的任何地方都不会这样做。

do I need id_counter ++; 我需要id_counter ++; and instance_counter ++; instance_counter ++; inside of my copy constructor? 在我的复制构造函数中?

Yes. 是。

Technically, both should be okay, at least in the near future. 从技术上讲,至少在不久的将来,两者都应该可以。

As is described link and link , size_t is the type of the return value of sizeof() operator and is guaranteed to hold the size of the largest object possible on the current platform. linklink所述size_tsizeof()运算符的返回值的类型,并保证保持当前平台上可能的最大对象的大小。 It's usually unsigned also. 通常也unsigned

And yeah, using unsigned long long is unlikely to cause any problem in the near future. 是的, unsigned long long使用unsigned long long不太可能在不久的将来引起任何问题。 Yet size_t might gives you an extra advantage when you migrate to, say, 128bit environment, on maximum compatibility. 但是,当迁移到例如128位环境时, size_t可能会为您带来额外的优势,即具有最大的兼容性。


But if your code depends on the fact that unsigned long long has at least 0~2^64-1 it's probably not a good idea to switch to size_t . 但是,如果您的代码取决于unsigned long long 至少为0〜2 ^ 64-1的事实,那么切换到size_t可能不是一个好主意。


yes, you need to update the counter in your copy constructor to get it straight. 是的,您需要更新副本构造函数中的计数器,以使其保持直线。


PS I don't see why you would want to: 附言:我不明白您为什么要:

Nothing instance; 
instance(Nothing);

maybe some member function like static Nothing Nothing::instance() to get a new instance? 也许某些成员函数(如static Nothing Nothing::instance()可以获取新实例? // I just don't see why you would want to call a copy-ctor on a type instead of an existing instance . //我只是不明白为什么要在类型而不是现有实例上调用copy-ctor。

And BTW you can always call printf() and flush() from constructors and destructors to examine their order of execution. 而且顺便说一句,您始终可以从构造函数和析构函数调用printf()flush()来检查它们的执行顺序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM