临时类对象 我现在正在阅读C++入门第五版,这是书中的代码示例之一。我对这行代码感到困惑auto-ret=StrBlobPtr(*this,data->size())如果我理解正确,这一行将创建一个临时StrBlobPtr对象,它调用这个构造函数StrBlobPtr(StrBlob&a,size\t sz=0):wptr(a.data),curr(sz){},但我不理解auto ret=如何从临时对象获取返回值,所以我的问题是 ret如何获取由StrBlobPtr创建的对象 end如何返回保存std::shared\u ptr数据中最后一个值的StrBlobPtr在StrBlob类中

临时类对象 我现在正在阅读C++入门第五版,这是书中的代码示例之一。我对这行代码感到困惑auto-ret=StrBlobPtr(*this,data->size())如果我理解正确,这一行将创建一个临时StrBlobPtr对象,它调用这个构造函数StrBlobPtr(StrBlob&a,size\t sz=0):wptr(a.data),curr(sz){},但我不理解auto ret=如何从临时对象获取返回值,所以我的问题是 ret如何获取由StrBlobPtr创建的对象 end如何返回保存std::shared\u ptr数据中最后一个值的StrBlobPtr在StrBlob类中,c++,c++11,constructor,C++,C++11,Constructor,我所说的代码部分位于底部 #pragma once #include <vector> #include <string> #include <initializer_list> #include<stdexcept> #include <memory> #include <exception> using std::vector; using std::string; class StrBlobPtr; class

我所说的代码部分位于底部

#pragma once

#include <vector>
#include <string>
#include <initializer_list>
#include<stdexcept>
#include <memory>
#include <exception>

using std::vector;
using std::string;

class StrBlobPtr;

class StrBlob {
public:
    using size_type = vector<string>::size_type;
    friend class StrBlobPtr;

    StrBlobPtr begin();
    StrBlobPtr end();

    StrBlob() : data(std::make_shared<vector<string>>()) {}
    StrBlob(std::initializer_list<string> il)
        : data(std::make_shared<vector<string>>(il))
    {
    }

    size_type size() const { return data->size(); }
    bool empty() const { return data->empty(); }

    void push_back(const string& t) { data->push_back(t); }
    void pop_back()
    {
        check(0, "pop_back on empty StrBlob");
        data->pop_back();
    }

    std::string& front()
    {
        check(0, "front on empty StrBlob");
        return data->front();
    }

    std::string& back()
    {
        check(0, "back on empty StrBlob");
        return data->back();
    }

    const std::string& front() const
    {
        check(0, "front on empty StrBlob");
        return data->front();
    }
    const std::string& back() const
    {
        check(0, "back on empty StrBlob");
        return data->back();
    }

private:
    void check(size_type i, const string& msg) const
    {
        if (i >= data->size()) throw std::out_of_range(msg);
    }
private:
    std::shared_ptr<vector<string>> data;
};

class StrBlobPtr {
public:
    StrBlobPtr() : curr(0) {}
    StrBlobPtr(StrBlob& a, size_t sz = 0) : wptr(a.data), curr(sz) {}
    bool operator!=(const StrBlobPtr& p) { return p.curr != curr; }
    string& deref() const
    {
        auto p = check(curr, "dereference past end");
        return (*p)[curr];
    }
    StrBlobPtr& incr()
    {
        check(curr, "increment past end of StrBlobPtr");
        ++curr;
        return *this;
    }

private:
    std::shared_ptr<vector<string>> check(size_t i, const string& msg) const
    {
        auto ret = wptr.lock();
        if (!ret) throw std::runtime_error("unbound StrBlobPtr");
        if (i >= ret->size()) throw std::out_of_range(msg);
        return ret;
    }
    std::weak_ptr<vector<string>> wptr;
    size_t curr;
};
StrBlobPtr StrBlob::begin() { return StrBlobPtr(*this); }
StrBlobPtr StrBlob::end()
{
    auto ret = StrBlobPtr(*this, data->size());
    return ret;
}
#pragma一次
#包括
#包括
#包括
#包括
#包括
#包括
使用std::vector;
使用std::string;
StrBlobPtr类;
类StrBlob{
公众:
使用size\u type=vector::size\u type;
朋友类strblopptr;
StrBlobPtr begin();
StrBlobPtr end();
StrBlob():数据(std::make_shared()){}
StrBlob(std::初始值设定项\u列表il)
:数据(标准::使共享(il))
{
}
size_type size()常量{返回数据->size();}
bool empty()常量{return data->empty();}
void push_back(const string&t){data->push_back(t);}
void pop_back()
{
勾选(0,“空StrBlob上的pop_返回”);
数据->弹出返回();
}
std::string和front()
{
勾选(0,“空StrBlob上的前端”);
返回数据->前端();
}
std::string&back()
{
选中(0,“返回空StrBlob”);
返回数据->返回();
}
常量std::string&front()常量
{
勾选(0,“空StrBlob上的前端”);
返回数据->前端();
}
常量std::string&back()常量
{
选中(0,“返回空StrBlob”);
返回数据->返回();
}
私人:
无效检查(大小\类型i,常量字符串和消息)常量
{
如果(i>=data->size())抛出std::超出范围(msg);
}
私人:
std::共享的ptr数据;
};
类strBlopTR{
公众:
StrBlobPtr():curr(0){}
StrBlobPtr(StrBlob&a,size_t sz=0):wptr(a.data),curr(sz){}
布尔运算符!=(常量StrBlobPtr&p){return p.curr!=curr;}
string&deref()常量
{
自动p=检查(当前,“取消引用结束”);
返回(*p)[货币];
}
StrBlobPtr&incr()
{
支票(当前,“超过StrBlobPtr末尾的增量”);
++咖喱;
归还*这个;
}
私人:
std::共享检查(大小、常量字符串和消息)常量
{
auto-ret=wptr.lock();
如果(!ret)抛出std::runtime_错误(“unbound StrBlobPtr”);
如果(i>=ret->size())抛出std::超出范围(msg);
返回ret;
}
标准:弱ptr wptr;
货币大小;
};
StrBlobPtr StrBlob::begin(){返回StrBlobPtr(*this);}
StrBlobPtr StrBlob::end()
{
auto-ret=StrBlobPtr(*this,data->size());
返回ret;
}

由于c++11,如果不想显式指定变量类型,可以使用关键字auto,但不要将其与自动变量混淆,这意味着它们会在块的末尾被删除(您可以阅读以下内容:)

因此,在调用函数的第一行StrBlobPtr::end()构造函数时,将创建类型为StrBlobPtr的对象,在调用该复制构造函数后,将创建另一个对象,但该对象将一直存在,直到到达块的末尾(在本例中为函数的末尾)。之后第一个对象被删除,所以您只有复制构造函数创建的对象。请查看此帖子:

你们的第二个问题是关于归还物品,若我是对的话。在C++中这样做时必须小心。假设您在代码中的某个地方调用了StrBlobPtr::end():

StrBlobPtr obj; 
obj = StrBlobPtr::end();
所以您在第一行创建了对象,在调用函数之后,返回相同类型的对象,但该对象仅存在于此行中,在调用StrBlobPtr::operator=(StrBlobPtr x)之后,从函数返回的对象被删除,并且它不存在于内存中,所以您不能执行以下操作:

StrBlobPtr* obj; 
obj = StrBlobPtr::end();

因为在第二行指针obj拥有删除对象的地址之后,若您尝试使用它,您将得到异常。所以,若要从函数返回整个对象,必须小心,有时最好使用操作符new在动态内存中创建对象,并从函数返回引用或指针。重要的是,如果您需要创建对象,并调用复制构造函数返回这个对象,那么您经常调用这个函数。C++中的

初始化是…在这种情况下,您得到了。谢谢您的回答。
auto x=T()
tx()相同(除了不被解释为函数声明)谢谢你的回答,我想得不对,我认为StrBlobPtr创建的临时对象在调用后立即被删除,并且从未复制到ret中。@verynice请注意,编译器是智能的,可能会消除1的答案中暗示的所有复制
ret
将直接构造,而不是复制临时对象,临时对象将根本不存在。这种行为是C++17和更新版本所要求的,但在较旧的标准下编译器经常观察到