【问题标题】:C++ get array key in constructor of array of a custom class/struct?C ++在自定义类/结构的数组的构造函数中获取数组键?
【发布时间】:2010-07-11 17:06:28
【问题描述】:

如果我有这样一个简单的类:

class MyClass
{
    MyClass(){}
    ~MyClass(){}
public:   
    int myArrayKeyValue;
};

然后,我创建了这些类的数组:

MyClass testing[10];

如何在构造函数中访问数组键,以便为数组的每个元素适当地设置myArrayKeyValue?所以我得到了这个:

testing[0].myArrayKeyValue = 0;
testing[1].myArrayKeyValue = 1;
testing[2].myArrayKeyValue = 2;
testing[3].myArrayKeyValue = 3;
etc...

可以在构造函数中完成吗?还是我必须遍历数组并手动分配值?

【问题讨论】:

    标签: c++ arrays array-key


    【解决方案1】:

    可以在构造函数中实现吗?

    没有。

    还是我必须循环遍历数组并手动分配值?

    是的。尽管您可能能够重新设计,以便您不需要了解这些实例内部之外的索引。

    可能的替代方案包括:

    • map<int, MyClass>这样的关联容器
    • set<MyClass>,键值为排序标准

    【讨论】:

      【解决方案2】:

      您不能直接从构造函数中执行此操作;它无法访问对象在数组中的位置。您必须编写一个循环来进行初始化。

      或者——我什至对提到这一点感到有点反感——使用从构造函数中递增的全局或静态计数器。保证构建顺序从数组的开始到结束,所以这在技术上是可行的。但这太可怕了。

      (顺便说一句,您示例中的构造函数是私有的,因此数组声明甚至无法编译。)

      【讨论】:

        【解决方案3】:

        在构造函数中递增的简单的从零开始的static 成员应该这样做。不过,您需要在创建数组之前重置它。这是否是一个好主意是一个完全不同的话题:)

        【讨论】:

        • 那是灾难的根源。如果您需要同时在两个不同的线程中执行算法怎么办?
        • 好吧,并不是所有的代码都是线程化的。但我没说这是个好主意,不是吗? :)
        • 如果他建立自己的操作系统怎么办?请不要对适合给定信息的解决方案投反对票。如果它是多线程的,他会精确的。
        • 问题是语言允许你解决这个问题。它还允许您在...脚下射击自己。您应该知道在线程代码中使用未受保护的static 成员更好。然后,您还应该在触发之前阅读问题和答案。哦,好吧,现在的孩子们:)
        • 我的阅读不好,我看不到它应该在多线程中使用的任何地方(如果不是,只要我们知道它不会,我们可以选择不受保护静态)......无论如何,显然你赎回了你的反对票,所以我想我们很清楚:)
        【解决方案4】:

        这样的事情是可能的:

        class MyClass { 
        public: 
          MyClass(int index) { myArrayKeyValue = index; } 
          ~MyClass();
        private:
        int myArrayKeyValue;
        }; 
        
        int main() 
        { 
          MyClass testing[5] = { MyClass(1), MyClass (2), 
                           MyClass (3), MyClass (4), MyClass (5) };
        
          return 0; 
        }
        

        【讨论】:

        • 可能,但显然没有压缩:/您是否愿意编写(或复制/粘贴)尽可能多的显式结构?
        • 这取决于是否有人想要初始化具有不同值的对象数组而不是使用循环序列。
        【解决方案5】:

        考虑您想要的最终结果并尝试通过其他方式实现它可能很有价值。

        一种方法可能是这样的:

        std::vector<MyClass> v;
        for (size_t i=0; i<nCount; i++)
            v.push_back(MyClass(static_cast<int>(i)));
        

        【讨论】:

        • 那将是循环解决方案(对我来说最好,但他似乎想要一个构造方法),但在这种情况下 myArrayKeyValue 应该直接为 size_t ,以避免 static_cast 例如值大于2^15(size_t 等价于 unsigned int)。
        【解决方案6】:

        您也可以使用静态计数器,如下所示:

        class MyClass {
            static size_t static_counter;
        
            size_t m_value;
        public:
            MyClass() {
                m_value = static_counter++;
            }
        
            inline static void reset() {
                static_counter = 0;
            }
        
            inline size_t get_value() const {
                return m_value;
            }
        };
        
        size_t MyClass::static_counter = 0;
        

        但是你有责任手动重置,否则会有内存侵入。这将通过在更高级别封装(在析构函数中重置)来纠正。

        编辑:我和 Nikolai N Fetissov 有同样的想法,并且预期:静态成员本身不能用于多线程程序。

        【讨论】:

        • 投反对票?你肯定不会鼓励其他人用经过测试的代码来回答。
        • 这种静态初始化不是很好的解决方案。是的,这是可能的,而且它会起作用,但正是因为你提到它的原因是不好的。
        • 只有当程序注定是多线程的,尤其是当我们不知道我们在做什么时,这才是糟糕的。为什么要对一个明显显示其弱点的解决方案投反对票?无论是单线程还是多线程,都由主题的创建者来选择。
        • 如果多线程的编程习惯不好,这种做法变得越来越普遍,你为什么要给出它作为答案,特别是如果你不知道他试图使用它的上下文?静态初始化不好,简单明了。它的用途有限,但这不是其中之一。
        • 我对它投了反对票,原因与我对Nikolai's answer 投反对票的原因相同,其中解释了为什么这是一个坏主意。很抱歉懒得重复,我认为那里的解释已经足够清楚了。
        猜你喜欢
        • 2018-11-13
        • 1970-01-01
        • 1970-01-01
        • 2012-10-20
        • 2019-11-26
        • 2020-10-18
        • 2021-12-24
        • 1970-01-01
        • 2013-03-03
        相关资源
        最近更新 更多