Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.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
关于类对象的编译器行为我不知道';我不明白 我是NoOB,仍然在学习C++语言。问题是,在做一本书中的练习时,我遇到了一个我不理解的编译器行为_C++_Class_Compiler Construction_Constructor_Destructor_C++11 - Fatal编程技术网

关于类对象的编译器行为我不知道';我不明白 我是NoOB,仍然在学习C++语言。问题是,在做一本书中的练习时,我遇到了一个我不理解的编译器行为

关于类对象的编译器行为我不知道';我不明白 我是NoOB,仍然在学习C++语言。问题是,在做一本书中的练习时,我遇到了一个我不理解的编译器行为,c++,class,compiler-construction,constructor,destructor,c++11,C++,Class,Compiler Construction,Constructor,Destructor,C++11,头文件 // stock10.h -- Stock class declaration with constructors, destructor added #ifndef STOCK10_H_ #define STOCK10_H_ #include <string> class Stock { private: std::string company; long shares; double share_val; double total_v

头文件

// stock10.h -- Stock class declaration with constructors, destructor added

#ifndef STOCK10_H_
#define STOCK10_H_

#include <string>

class Stock
{
private:
    std::string company;
    long shares;
    double share_val;
    double total_val;
    void set_tot() { total_val = shares * share_val; }
public:
    // two constructors
    Stock(); // default constructor
    Stock(const std::string & co, long n = 0, double pr = 0.0);
    ~Stock(); // noisy destructor
    void buy(long num, double price);
    void sell(long num, double price);
    void update(double price);
    void show();
};

#endif
编译器不应该:
1.使用构造函数创建临时对象
2.将该对象分配给stock1对象
3.销毁临时对象

信息不是应该说漂亮的食物而不是纳米智能吗


我不明白。有什么帮助吗?

您没有定义赋值运算符,因此如果您使用的是C++11编译器,它可能会使用移动赋值运算符,该运算符交换对象,然后删除临时对象的新内容,临时对象以前位于
stock1


至少,这是观察到的行为。然而,ecatmur是正确的,您的类不应该收到隐式移动赋值运算符。这当然可能是一个编译器错误。

我看不出您的代码有什么直接的错误,但您可能应该实现一个复制构造函数和赋值运算符,以确保复制操作正确执行

大概是这样的:

class Stock
{
    // ...

public:
    // ...

    Stock(const Stock &other)
        : company(other.company), shares(other.shares),
          share_val(other.share_val), total_val(other.total_val)
        { }

    Stock &operator=(const Stock &other)
        {
            company   = other.company;
            shares    = other.shares;
            share_val = other.share_val;
            total_val = other.total_val;

            return *this;
        }

    // ...
};

有关复制构造函数的更多信息,请参见例如。对于赋值运算符,请参见,例如:

您尚未编写复制赋值运算符
Stock::operator=(const Stock&)
或移动赋值运算符
Stock::operator=(Stock&&)
,因此您的赋值
stock1=Stock(“俏皮食品”,10,50.0)将调用隐式定义的复制/移动分配运算符:

12.8复制和移动类对象[class.copy] 18-如果类定义未显式声明副本赋值运算符,则隐式声明一个。如果 类定义声明一个移动构造函数或移动赋值运算符,即隐式声明的副本 分配操作员定义为已删除;否则,它被定义为默认值(8.4)。
28-非联合类X的隐式定义的复制/移动赋值运算符执行成员复制- /移动其子对象的指定

由于类具有用户定义的析构函数,因此不会隐式定义移动分配运算符(12.8:20),因此将调用隐式定义的复制分配运算符:

20-如果类X的定义没有显式声明移动赋值运算符,则会隐式声明移动赋值运算符 声明为默认的当且仅当[…]

  • X没有用户声明的析构函数
因此,
库存(“俏皮食品”,10,50.0)
将以成员身份复制到
stock1
中,然后销毁;因此,显示的消息将是“再见,漂亮的食物!”

这里有一个SSCCE:

#include <iostream>
#include <string>
struct S {
    std::string s;
    S(const std::string &s): s(s) { std::cout << "S(" << s << ")\n"; }
    ~S() { std::cout << "~S(" << s << ")\n"; }
};
int main() {
    S a("a");
    a = S("b");
}


在我们回答你的问题之前,你最好给我们看看你的班级。至少是类声明、复制构造函数和赋值运算符(如果您实现了一个,那么您可能应该实现它)。@Joachim Pileborg对此表示抱歉。我添加了类实现文件。您能同时添加头文件吗?我们可能还需要看看您如何声明类成员变量。我无法重现您的输出。再见,漂亮的食物。输出不匹配<代码>“将stock1分配给stock2:\n”未显示。请发布实际输出。但我不是在创建对象。它已经创建了。在你的例子中是bar=Foo(某物)。酒吧已经开张了created@Kurospidey当你做
stock1=Stock(“美味食品”,10,50.0),编译器将创建一个临时对象,然后使用
stock1
的赋值运算符复制临时对象。如果您没有自己的赋值运算符,那么编译器生成的赋值运算符可能会做错误的事情。@JoachimPileborg,我理解。但在那之后,它不应该摧毁那个临时物体吗?所以信息应该是“再见,俏皮食品”,因为它正在破坏公司名为俏皮食品的物体。相反,它会说“再见,NanoSmart”,就像它正在销毁stock1对象一样,这不值得担心,我指的是赋值运算符。不过也是一样。请注意,使用“移动指定”操作符后,temp对象可能很好地保存了
stock1
以前的内容。@christorcreutzig移动赋值运算符根据12.8:20被用户声明的析构函数抑制。仅执行默认构造函数/赋值的复制构造函数/赋值是多余的,并且可能是错误源。如果类没有指针成员,通常不需要它们。谢谢你的回答。问题是,我在学习语言的同时,正在跟随一本书。在这个特别的练习中,作者声称程序输出应该是我现在使用的工具。我认为也应该是这个问题,但编译器不这么认为,我不知道为什么。@同上,在这种情况下,编译器默认值显然有错误,否则OP不会发布问题。@JoachimPileborg,你试过OP的代码吗?你是否重现了OP的异常结果,你的建议是否为你修复了它?对我来说,OP的代码工作正常,没有任何更改。问题是,为什么不显示该消息。OP索赔
再见,NanoSmart已打印。@juanchopanza OP不正确或正在使用不一致的实现。看起来是这样的。”。我还不能在各种GCC上复制它。谢谢大家的评论。我正在使用mingw(可能是一个奇怪的版本)
stock1 = Stock("Nifty Foods", 10, 50.0); // temp object
class Stock
{
    // ...

public:
    // ...

    Stock(const Stock &other)
        : company(other.company), shares(other.shares),
          share_val(other.share_val), total_val(other.total_val)
        { }

    Stock &operator=(const Stock &other)
        {
            company   = other.company;
            shares    = other.shares;
            share_val = other.share_val;
            total_val = other.total_val;

            return *this;
        }

    // ...
};
#include <iostream>
#include <string>
struct S {
    std::string s;
    S(const std::string &s): s(s) { std::cout << "S(" << s << ")\n"; }
    ~S() { std::cout << "~S(" << s << ")\n"; }
};
int main() {
    S a("a");
    a = S("b");
}
S(a)
S(b)
~S(b)
~S(b)