Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++指针参数:创建指向的值的副本是否有意义,然后将副本存储为指针? 我把一个项目移植到C++,因为我在C中开发了一个性能上限。这是我第一次使用C++,但是我发现自己做了很多看起来不太正确的事情……_C++_Class_Pointers - Fatal编程技术网

C++指针参数:创建指向的值的副本是否有意义,然后将副本存储为指针? 我把一个项目移植到C++,因为我在C中开发了一个性能上限。这是我第一次使用C++,但是我发现自己做了很多看起来不太正确的事情……

C++指针参数:创建指向的值的副本是否有意义,然后将副本存储为指针? 我把一个项目移植到C++,因为我在C中开发了一个性能上限。这是我第一次使用C++,但是我发现自己做了很多看起来不太正确的事情……,c++,class,pointers,C++,Class,Pointers,考虑以下抽象示例: class ClassC { ClassC::ClassC(int option) { //do something } } class ClassB { ClassC* objC ClassB::ClassB(ClassC* objC) { this->objC = new ClassC(*objC); } } class ClassA { void function

考虑以下抽象示例:

class ClassC
{
    ClassC::ClassC(int option)
    {
        //do something
    }
}

class ClassB
{
    ClassC* objC

    ClassB::ClassB(ClassC* objC)
    {
        this->objC = new ClassC(*objC);
    }
}

class ClassA
{
    void functionA(void)
    {
        ClassB objB (&ClassC(2));
    }
}
ClassA有一个创建ClassB的函数。ClassB的构造函数接受一个ClassC,objC。objC是通过引用传递的,因为ClassC不是基元类型,但它是通过引用存储的,因为ClassC没有默认构造函数。但是,由于objC是在静态内存中创建的,并且在functionA完成时将被销毁,因此ClassB需要将objC指向的值复制到动态内存中,然后存储指向该副本的指针

这对我来说似乎很全面,让我觉得我在错误地接近某件事。在C++中,这是标准的事情吗?< /P> 编辑:每个人似乎都在说B类objB&ClassC2;不正确,因为ClassC对象的值将在ClassB复制它之前丢失。但我已经编译了我的示例,事实并非如此。以下是修订后的工作代码:

这是一件坏事。您将获得一个临时对象的地址,该地址将在此行后消失。如前所述,尝试使用引用而不是指针。大多数情况下,您可以用引用替换指针,这是一种非常安全的方法,它永远不会为NULL

你可以写

class ClassB
{
    ClassC& objC;

    ClassB::ClassB(const ClassC& objC) :
        objC(objC)
    {
    }
}
这是一件坏事。您将获得一个临时对象的地址,该地址将在此行后消失。如前所述,尝试使用引用而不是指针。大多数情况下,您可以用引用替换指针,这是一种非常安全的方法,它永远不会为NULL

你可以写

class ClassB
{
    ClassC& objC;

    ClassB::ClassB(const ClassC& objC) :
        objC(objC)
    {
    }
}

不确定您真正的问题是什么,但您的代码似乎很脆弱。我想重写您的代码,如您所示:

class ClassC
{
    explicit ClassC(int option)
//  ^^^^^^^^ stop implicit conversion, if constructor takes one parameter
    {
        //do something
    }
};

class ClassB
{
    ClassC objC;                         // store by value instead of pointer. 
                                         // Even smart pointer will be better option than raw pointer

    explicit ClassB(const ClassC& objC)  // pass by const reference instead
    : objC(objC)                         // use member initializer list to initialize members
    {
    }
};

class ClassA
{
    void functionA(void)
    {
        ClassB objB(ClassC(2));
    }
};

不确定您真正的问题是什么,但您的代码似乎很脆弱。我想重写您的代码,如您所示:

class ClassC
{
    explicit ClassC(int option)
//  ^^^^^^^^ stop implicit conversion, if constructor takes one parameter
    {
        //do something
    }
};

class ClassB
{
    ClassC objC;                         // store by value instead of pointer. 
                                         // Even smart pointer will be better option than raw pointer

    explicit ClassB(const ClassC& objC)  // pass by const reference instead
    : objC(objC)                         // use member initializer list to initialize members
    {
    }
};

class ClassA
{
    void functionA(void)
    {
        ClassB objB(ClassC(2));
    }
};

删除临时文件的地址并保存下来供以后使用是一个重大的禁忌

ClassB objB (&ClassC(2));  // taking address of temporary
此外,即使在函数参数列表中传递临时变量的const引用,其生存期也不会比函数调用延长得更多。也就是说,一旦构造器完成激发,引用即被终止,因此:

class ClassB
{
    const ClassC& objC;

public:
    ClassB(const ClassC& objC) : objC(objC)
    {
    }
};
也不行

如果您这样做,它将起作用:

ClassC objC;
ClassB objB(objC);
但话说回来,你的原始样品也是如此

保证外部对象生存期的一种方法是通过智能指针所有权动态分配对象。考虑这一点:

class ClassB
{
    std::shared_ptr<ClassC> ptrC;

public:

    ClassB(std::shared_ptr<ClassC> ptrC)
        : ptrC(ptrC)
    {
        // access the instance with ptrC->member()
    }
};
这使得ClassA中的代码简单如下:

ClassB objB(2);

这将调用ClassB::ClassBint,将提供的参数传递给ClassC类型的内部objC对象实例的构造。

获取临时对象的地址并将其保存以供以后使用是一个很大的禁忌

ClassB objB (&ClassC(2));  // taking address of temporary
此外,即使在函数参数列表中传递临时变量的const引用,其生存期也不会比函数调用延长得更多。也就是说,一旦构造器完成激发,引用即被终止,因此:

class ClassB
{
    const ClassC& objC;

public:
    ClassB(const ClassC& objC) : objC(objC)
    {
    }
};
也不行

如果您这样做,它将起作用:

ClassC objC;
ClassB objB(objC);
但话说回来,你的原始样品也是如此

保证外部对象生存期的一种方法是通过智能指针所有权动态分配对象。考虑这一点:

class ClassB
{
    std::shared_ptr<ClassC> ptrC;

public:

    ClassB(std::shared_ptr<ClassC> ptrC)
        : ptrC(ptrC)
    {
        // access the instance with ptrC->member()
    }
};
这使得ClassA中的代码简单如下:

ClassB objB(2);
这将调用ClassB::ClassBint,将提供的参数传递给ClassC类型的内部objC对象实例的构造。

ClassC的构造函数与此无关,因为将调用的是复制构造函数

class ClassC
{
    ClassC(int option) // defines a constructor that takes an int
    {
        //do something
    }
}

class ClassB
{
    ClassC* objC

    ClassB(ClassC* objC)
    {
        this->objC = new ClassC(*objC); // dereferences objC calling ClassC::ClassC(const Class& obj) - the default copy constructor.
    }
}

class ClassA
{
    void functionA(void)
    {
        ClassB objB (&ClassC(2)); // passing a reference to a temporary ... bad idea, but since it is copied in ClassB (the object, not the pointer), it will appear okay - if your compiler lets this compile (newer ones should/will likely throw an error "cannot take address of rvalue temporary")
    }
}
总而言之,有了前面提到的许多建议,这段代码会更好,但值得注意的是,ClassC的复制构造函数就是在ClassB中调用的构造函数。

您的ClassC构造函数与此无关,因为将调用的是复制构造函数

class ClassC
{
    ClassC(int option) // defines a constructor that takes an int
    {
        //do something
    }
}

class ClassB
{
    ClassC* objC

    ClassB(ClassC* objC)
    {
        this->objC = new ClassC(*objC); // dereferences objC calling ClassC::ClassC(const Class& obj) - the default copy constructor.
    }
}

class ClassA
{
    void functionA(void)
    {
        ClassB objB (&ClassC(2)); // passing a reference to a temporary ... bad idea, but since it is copied in ClassB (the object, not the pointer), it will appear okay - if your compiler lets this compile (newer ones should/will likely throw an error "cannot take address of rvalue temporary")
    }
}

总而言之,有了前面提到的许多建议,这段代码会更好,但值得注意的是,ClassC的复制构造函数就是在ClassB中调用的构造函数。

您是否收到任何错误?它们是什么?B类objB和C2类;这是一个临时工的地址。这不是一件好事。您需要了解对象生存期和所有权语义。在c.1中,您需要担心的事情要少得多。如果可以避免,就不要使用指针。2.传递const ref而不是pointer除了模糊的建议之外,很难建议如何处理示例代码,因为您的意图并不十分清楚。是否有任何错误?它们是什么?B类objB和C2类;这是一个临时工的地址。这不是一件好事。您需要了解对象生存期和所有权语义。在c语言中,你不用担心这些事情

1.如果可以避免,就不要使用指针。2.传递常量引用而不是指针除了模糊的建议之外,很难建议如何处理示例代码,因为您的意图并不十分清楚。我们如何确保objC的生命周期比ClassB实例更长?我们如何从常量引用初始化引用?我不同意这个答案。我认为在大多数情况下,存储引用和存储指针一样糟糕,甚至更糟。另外,正如@WhozCraig所指出的,这段代码无法编译。是的,很抱歉。我想让成员objC不是一个引用,而是一个简单的ClassB成员,因为在我看来他想复制一个参数objC。我们如何确保objC比ClassB实例有更长的生命周期?我们如何从const引用初始化引用?我不同意这个答案。我认为在大多数情况下,存储引用和存储指针一样糟糕,甚至更糟。另外,正如@WhozCraig所指出的,这段代码无法编译。是的,很抱歉。我想让成员objC不是一个引用,而是一个简单的类b成员,因为在我看来,他想复制参数objC。在这段代码中,您创建一个临时类c,然后将引用传递给一个临时类,然后再次复制到objC中。我会将构造函数更改为显式ClassBClassC:objCstd::movec{},这将导致没有副本,因为临时值将被移动到classB构造函数参数中,因为它是一个右值,然后将用于移动构造objC。@MuhammadFaizan我明白你的意思。然而,将移动语义添加到OP atm中并没有太大价值。@MuhammadFaizan临时变量仍在作用域中,并且他没有存储引用,因此以这种方式使用它没有什么错。此外,ClassB将调用ClassC的复制构造函数,再次避免引用临时问题。移动语义只会有助于提高性能,避免复制所有这些副本。考虑到我认为OP正在寻找的东西,我也投了赞成票,认为这应该是公认的答案。我同意移动语义也是一种理想的方法。我发布的答案是为了涵盖OP寻找共享语义的可能性,但我认为这可能更符合他们的目的。作为旁注,这个答案与OP发布的没有动态内存的内容基本相同:传递临时,这没关系,因为它是通过动态内存分配在OP中复制的,这里是通过静态内存。在这段代码中,您创建了一个临时类C,然后将引用传递给一个临时类,然后再次将其复制到objC中。我会将构造函数更改为显式ClassBClassC:objCstd::movec{},这将导致没有副本,因为临时值将被移动到classB构造函数参数中,因为它是一个右值,然后将用于移动构造objC。@MuhammadFaizan我明白你的意思。然而,将移动语义添加到OP atm中并没有太大价值。@MuhammadFaizan临时变量仍在作用域中,并且他没有存储引用,因此以这种方式使用它没有什么错。此外,ClassB将调用ClassC的复制构造函数,再次避免引用临时问题。移动语义只会有助于提高性能,避免复制所有这些副本。考虑到我认为OP正在寻找的东西,我也投了赞成票,认为这应该是公认的答案。我同意移动语义也是一种理想的方法。我发布的答案是为了涵盖OP寻找共享语义的可能性,但我认为这可能更符合他们的目的。作为旁注,这个答案与OP发布的没有动态内存的内容基本相同:传递临时,这是可以的,因为它是通过动态内存分配,在这里通过静态内存复制的。随机观察:我第一次学习C++,这是令人惊奇的,对于C或java中需要非常少的思想的最好的解决方案是移动语义或共享指针,这两个都是C++11的概念。我想知道,在新标准诞生之前,每个人是如何生存下来的:@MuhammadFaizan,经过仔细的编码。移动语义主要提供一种优化,就像以前一样,它涉及到对象的复制。然而,智能指针已经存在了相当长的一段时间。在这些模板之前,调试了很多,确保你正确地管理了你的内存。@ MuHurdAffiZAN是C发明的,C++是Bjarne first发明的,毫无疑问C++ 11对我们在C++中经历的许多问题来说是一个很长的时间缓解。完美转发严重改变了世界,例如。@WhozCraig一旦构造函数触发引用,就可以看到我的编辑。。。我尝试过编译它,但事实并非如此。我现在做这件事的方式是ac
最终产生了预期的结果,虽然语义上可能不正确。@WhozCraig最后一个出门的人关灯我必须承认我不完全理解智能指针,我相信你可以告诉我,但从你的描述来看,这似乎不一定是我要找的。在我的实际程序中,删除objC确实应该是ClassB的责任:这就是为什么ClassA在静态内存中创建它,然后ClassB将它复制到动态内存并负责删除它。有什么想法吗?随机观察:我第一次学习C++,这是令人惊奇的,对C或java中需要相当少的思想的最好的解决方案是移动语义或共享指针,它们都是C++ 11概念。我想知道,在新标准诞生之前,每个人是如何生存下来的:@MuhammadFaizan,经过仔细的编码。移动语义主要提供一种优化,就像以前一样,它涉及到对象的复制。然而,智能指针已经存在了相当长的一段时间。在这些模板之前,调试了很多,确保你正确地管理了你的内存。@ MuHurdAffiZAN是C发明的,C++是Bjarne first发明的,毫无疑问C++ 11对我们在C++中经历的许多问题来说是一个很长的时间缓解。完美转发严重改变了世界,例如。@WhozCraig一旦构造函数触发引用,就可以看到我的编辑。。。我尝试过编译它,但事实并非如此。我目前的做法确实产生了预期的结果,可能在语义上是不正确的。@WhozCraig最后一个出门的人关了灯我不得不承认我不完全理解智能指针,我相信你可以告诉我,但从你的描述来看,这似乎不一定是我要找的。在我的实际程序中,删除objC确实应该是ClassB的责任:这就是为什么ClassA在静态内存中创建它,然后ClassB将它复制到动态内存并负责删除它。有什么想法吗?